mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-02-25 00:54:44 +08:00
Compare commits
18 Commits
0e2ecdf93e
...
typescript
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d847ab8f6 | ||
|
|
8a2cd6c26e | ||
|
|
e0d8990e6a | ||
|
|
98ebdd78b2 | ||
|
|
ad4ba2c46d | ||
|
|
6d99db5fd1 | ||
|
|
beccfe522a | ||
|
|
ad8305ca52 | ||
|
|
6ca966e176 | ||
|
|
e16822760f | ||
|
|
c05e6d3cc9 | ||
|
|
1a8636bb5d | ||
|
|
8fed17b20f | ||
|
|
5314228b33 | ||
|
|
8258572e56 | ||
|
|
ecc71b76d1 | ||
|
|
1c2778fbf8 | ||
|
|
70b4cabb97 |
4536
dist/ueblueprint.js
vendored
4536
dist/ueblueprint.js
vendored
File diff suppressed because it is too large
Load Diff
12
dist/ueblueprint.min.js
vendored
12
dist/ueblueprint.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -413,7 +413,7 @@ export default class Blueprint extends IElement {
|
||||
this.entity = this.entity.mergeWith(element.entity)
|
||||
const additionalSerialization = atob(element.entity.ExportedNodes)
|
||||
this.template.getPasteInputObject().pasted(additionalSerialization)
|
||||
.forEach(node => node.entity.isExported = true)
|
||||
.forEach(node => node.entity._exported = true)
|
||||
continue
|
||||
}
|
||||
const name = element.entity.getObjectName()
|
||||
|
||||
107
js/Utility.js
107
js/Utility.js
@@ -1,7 +1,4 @@
|
||||
import ComputedType from "./entity/ComputedType.js"
|
||||
import Configuration from "./Configuration.js"
|
||||
import MirroredEntity from "./entity/MirroredEntity.js"
|
||||
import Union from "./entity/Union.js"
|
||||
|
||||
export default class Utility {
|
||||
|
||||
@@ -184,97 +181,6 @@ export default class Utility {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Attribute} a
|
||||
* @param {Attribute} b
|
||||
*/
|
||||
static equals(a, b) {
|
||||
while (a instanceof MirroredEntity) {
|
||||
a = a.get()
|
||||
}
|
||||
while (b instanceof MirroredEntity) {
|
||||
b = b.get()
|
||||
}
|
||||
// Here we cannot check both instanceof IEntity because this would introduce a circular include dependency
|
||||
if (/** @type {IEntity?} */(a)?.equals && /** @type {IEntity?} */(b)?.equals) {
|
||||
return /** @type {IEntity} */(a).equals(/** @type {IEntity} */(b))
|
||||
}
|
||||
a = Utility.sanitize(a)
|
||||
b = Utility.sanitize(b)
|
||||
if (a?.constructor === BigInt && b?.constructor === Number) {
|
||||
b = BigInt(b)
|
||||
} else if (a?.constructor === Number && b?.constructor === BigInt) {
|
||||
a = BigInt(a)
|
||||
}
|
||||
if (a === b) {
|
||||
return true
|
||||
}
|
||||
if (a instanceof Array && b instanceof Array) {
|
||||
return a.length === b.length && a.every((value, i) => Utility.equals(value, b[i]))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {Attribute | AttributeTypeDescription} T
|
||||
* @param {T} value
|
||||
* @returns {AttributeConstructor<T>}
|
||||
*/
|
||||
static getType(value) {
|
||||
if (value === null) {
|
||||
return null
|
||||
}
|
||||
if (value?.constructor === Object && /** @type {AttributeInformation} */(value)?.type instanceof Function) {
|
||||
return /** @type {AttributeInformation} */(value).type
|
||||
}
|
||||
return /** @type {AttributeConstructor<any>} */(value?.constructor)
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {Attribute} V
|
||||
* @template {AttributeConstructor<V>} C
|
||||
* @param {C} type
|
||||
* @returns {value is InstanceType<C>}
|
||||
*/
|
||||
static isValueOfType(value, type, acceptNull = false) {
|
||||
if (type instanceof MirroredEntity) {
|
||||
type = type.getTargetType()
|
||||
}
|
||||
return (acceptNull && value === null) || value instanceof type || value?.constructor === type
|
||||
}
|
||||
|
||||
/** @param {Attribute} value */
|
||||
static sanitize(value, targetType = /** @type {AttributeTypeDescription } */(value?.constructor)) {
|
||||
if (targetType instanceof Array) {
|
||||
targetType = targetType[0]
|
||||
}
|
||||
if (targetType instanceof ComputedType) {
|
||||
return value // The type is computed, can't say anything about it
|
||||
}
|
||||
if (targetType instanceof Union) {
|
||||
let type = targetType.values.find(t => Utility.isValueOfType(value, t, false))
|
||||
if (!type) {
|
||||
type = targetType.values[0]
|
||||
}
|
||||
targetType = type
|
||||
}
|
||||
if (targetType instanceof MirroredEntity) {
|
||||
if (value instanceof MirroredEntity) {
|
||||
return value
|
||||
}
|
||||
return Utility.sanitize(value, targetType.getTargetType())
|
||||
}
|
||||
if (targetType && !Utility.isValueOfType(value, targetType, true)) {
|
||||
value = targetType === BigInt
|
||||
? BigInt(/** @type {Number} */(value))
|
||||
: new /** @type {EntityConstructor} */(targetType)(value)
|
||||
}
|
||||
if (value instanceof Boolean || value instanceof Number || value instanceof String) {
|
||||
value = /** @type {TerminalAttribute} */(value.valueOf()) // Get the relative primitive value
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
@@ -334,11 +240,14 @@ export default class Utility {
|
||||
}
|
||||
|
||||
/** @param {String} value */
|
||||
static escapeString(value) {
|
||||
return value
|
||||
.replaceAll(new RegExp(`(${Configuration.stringEscapedCharacters.source})`, "g"), '\\$1')
|
||||
.replaceAll("\n", "\\n") // Replace newline with \n
|
||||
.replaceAll("\t", "\\t") // Replace tab with \t
|
||||
static escapeString(value, inline = true) {
|
||||
let result = value.replaceAll(new RegExp(`(${Configuration.stringEscapedCharacters.source})`, "g"), '\\$1')
|
||||
if (inline) {
|
||||
result = result
|
||||
.replaceAll("\n", "\\n") // Replace newline with \n
|
||||
.replaceAll("\t", "\\t") // Replace tab with \t
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/** @param {String} value */
|
||||
|
||||
@@ -24,7 +24,7 @@ export default function nodeColor(entity) {
|
||||
}
|
||||
switch (entity.getClass()) {
|
||||
case Configuration.paths.callFunction:
|
||||
return entity.bIsPureFunc
|
||||
return entity.bIsPureFunc?.valueOf()
|
||||
? Configuration.nodeColors.green
|
||||
: Configuration.nodeColors.blue
|
||||
case Configuration.paths.niagaraNodeFunctionCall:
|
||||
@@ -74,7 +74,7 @@ export default function nodeColor(entity) {
|
||||
return Configuration.nodeColors.intenseGreen
|
||||
}
|
||||
}
|
||||
if (entity.bIsPureFunc) {
|
||||
if (entity.bIsPureFunc?.valueOf()) {
|
||||
return Configuration.nodeColors.green
|
||||
}
|
||||
return Configuration.nodeColors.blue
|
||||
|
||||
@@ -20,7 +20,7 @@ export default function nodeTemplateClass(nodeEntity) {
|
||||
|| nodeEntity.getClass() === Configuration.paths.callArrayFunction
|
||||
) {
|
||||
const memberParent = nodeEntity.FunctionReference?.MemberParent?.path ?? ""
|
||||
const memberName = nodeEntity.FunctionReference?.MemberName
|
||||
const memberName = nodeEntity.FunctionReference?.MemberName?.valueOf()
|
||||
if (
|
||||
memberName && (
|
||||
memberParent === Configuration.paths.kismetMathLibrary
|
||||
@@ -96,13 +96,15 @@ export default function nodeTemplateClass(nodeEntity) {
|
||||
}
|
||||
return MetasoundNodeTemplate
|
||||
case Configuration.paths.niagaraNodeOp:
|
||||
if ([
|
||||
"Boolean::LogicEq",
|
||||
"Boolean::LogicNEq",
|
||||
"Numeric::Abs",
|
||||
"Numeric::Add",
|
||||
"Numeric::Mul",
|
||||
].includes(nodeEntity.OpName)) {
|
||||
if (
|
||||
[
|
||||
"Boolean::LogicEq",
|
||||
"Boolean::LogicNEq",
|
||||
"Numeric::Abs",
|
||||
"Numeric::Add",
|
||||
"Numeric::Mul",
|
||||
].includes(nodeEntity.OpName?.valueOf())
|
||||
) {
|
||||
return VariableOperationNodeTemplate
|
||||
}
|
||||
break
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import Configuration from "../Configuration.js"
|
||||
import Utility from "../Utility.js"
|
||||
import BooleanEntity from "../entity/BooleanEntity.js"
|
||||
import LinearColorEntity from "../entity/LinearColorEntity.js"
|
||||
import MirroredEntity from "../entity/MirroredEntity.js"
|
||||
import VectorEntity from "../entity/VectorEntity.js"
|
||||
|
||||
const sequencerScriptingNameRegex = /\/Script\/SequencerScripting\.MovieSceneScripting(.+)Channel/
|
||||
const keyNameValue = {
|
||||
@@ -56,18 +60,18 @@ export default function nodeTitle(entity) {
|
||||
switch (entity.getType()) {
|
||||
case Configuration.paths.asyncAction:
|
||||
if (entity.ProxyFactoryFunctionName) {
|
||||
return Utility.formatStringName(entity.ProxyFactoryFunctionName)
|
||||
return Utility.formatStringName(entity.ProxyFactoryFunctionName?.valueOf())
|
||||
}
|
||||
case Configuration.paths.actorBoundEvent:
|
||||
case Configuration.paths.componentBoundEvent:
|
||||
return `${Utility.formatStringName(entity.DelegatePropertyName)} (${entity.ComponentPropertyName ?? "Unknown"})`
|
||||
return `${Utility.formatStringName(entity.DelegatePropertyName?.valueOf())} (${entity.ComponentPropertyName?.valueOf() ?? "Unknown"})`
|
||||
case Configuration.paths.callDelegate:
|
||||
return `Call ${entity.DelegateReference?.MemberName ?? "None"}`
|
||||
return `Call ${entity.DelegateReference?.MemberName?.valueOf() ?? "None"}`
|
||||
case Configuration.paths.createDelegate:
|
||||
return "Create Event"
|
||||
case Configuration.paths.customEvent:
|
||||
if (entity.CustomFunctionName) {
|
||||
return entity.CustomFunctionName
|
||||
return entity.CustomFunctionName?.valueOf()
|
||||
}
|
||||
case Configuration.paths.dynamicCast:
|
||||
if (!entity.TargetType) {
|
||||
@@ -77,7 +81,7 @@ export default function nodeTitle(entity) {
|
||||
case Configuration.paths.enumLiteral:
|
||||
return `Literal enum ${entity.Enum?.getName()}`
|
||||
case Configuration.paths.event:
|
||||
return `Event ${(entity.EventReference?.MemberName ?? "").replace(/^Receive/, "")}`
|
||||
return `Event ${(entity.EventReference?.MemberName?.valueOf() ?? "").replace(/^Receive/, "")}`
|
||||
case Configuration.paths.executionSequence:
|
||||
return "Sequence"
|
||||
case Configuration.paths.forEachElementInEnum:
|
||||
@@ -85,9 +89,9 @@ export default function nodeTitle(entity) {
|
||||
case Configuration.paths.forEachLoopWithBreak:
|
||||
return "For Each Loop with Break"
|
||||
case Configuration.paths.functionEntry:
|
||||
return entity.FunctionReference?.MemberName === "UserConstructionScript"
|
||||
return entity.FunctionReference?.MemberName?.valueOf() === "UserConstructionScript"
|
||||
? "Construction Script"
|
||||
: entity.FunctionReference?.MemberName
|
||||
: entity.FunctionReference?.MemberName?.valueOf()
|
||||
case Configuration.paths.functionResult:
|
||||
return "Return Node"
|
||||
case Configuration.paths.ifThenElse:
|
||||
@@ -99,35 +103,29 @@ export default function nodeTitle(entity) {
|
||||
case Configuration.paths.materialExpressionComponentMask: {
|
||||
const materialObject = entity.getMaterialSubobject()
|
||||
return `Mask ( ${Configuration.rgba
|
||||
.filter(k => /** @type {MirroredEntity<any>} */(materialObject[k]).get() === true)
|
||||
.filter(k => /** @type {MirroredEntity<typeof BooleanEntity>} */(materialObject[k]).getter().value === true)
|
||||
.map(v => v + " ")
|
||||
.join("")})`
|
||||
}
|
||||
case Configuration.paths.materialExpressionConstant:
|
||||
input ??= [entity.getCustomproperties().find(pinEntity => pinEntity.PinName == "Value")?.DefaultValue]
|
||||
input ??= [entity.getCustomproperties().find(pinEntity => pinEntity.PinName.valueOf() == "Value")?.DefaultValue]
|
||||
case Configuration.paths.materialExpressionConstant2Vector:
|
||||
input ??= [
|
||||
entity.getCustomproperties().find(pinEntity => pinEntity.PinName == "X")?.DefaultValue,
|
||||
entity.getCustomproperties().find(pinEntity => pinEntity.PinName == "Y")?.DefaultValue,
|
||||
entity.getCustomproperties().find(pinEntity => pinEntity.PinName?.valueOf() == "X")?.DefaultValue,
|
||||
entity.getCustomproperties().find(pinEntity => pinEntity.PinName?.valueOf() == "Y")?.DefaultValue,
|
||||
]
|
||||
case Configuration.paths.materialExpressionConstant3Vector:
|
||||
if (!input) {
|
||||
/** @type {VectorEntity} */
|
||||
const vector = entity.getCustomproperties()
|
||||
.find(pinEntity => pinEntity.PinName == "Constant")
|
||||
?.DefaultValue
|
||||
input = [vector.X, vector.Y, vector.Z]
|
||||
}
|
||||
case Configuration.paths.materialExpressionConstant4Vector:
|
||||
if (!input) {
|
||||
/** @type {LinearColorEntity} */
|
||||
const vector = entity.getCustomproperties()
|
||||
.find(pinEntity => pinEntity.PinName == "Constant")
|
||||
.find(pinEntity => pinEntity.PinName?.valueOf() == "Constant")
|
||||
?.DefaultValue
|
||||
input = [vector.R, vector.G, vector.B, vector.A].map(v => v.valueOf())
|
||||
input = vector instanceof VectorEntity ? [vector.X, vector.Y, vector.Z].map(v => v.valueOf())
|
||||
: vector instanceof LinearColorEntity ? [vector.R, vector.G, vector.B, vector.A].map(v => v.valueOf())
|
||||
: /** @type {Number[]} */([])
|
||||
}
|
||||
if (input.length > 0) {
|
||||
return input.map(v => Utility.printExponential(v)).reduce((acc, cur) => acc + "," + cur)
|
||||
return input.map(v => Utility.printExponential(v)).join(",")
|
||||
}
|
||||
break
|
||||
case Configuration.paths.materialExpressionFunctionInput: {
|
||||
@@ -165,7 +163,7 @@ export default function nodeTitle(entity) {
|
||||
return "Output"
|
||||
case Configuration.paths.spawnActorFromClass:
|
||||
let className = entity.getCustomproperties()
|
||||
.find(pinEntity => pinEntity.PinName == "ReturnValue")
|
||||
.find(pinEntity => pinEntity.PinName.valueOf() == "ReturnValue")
|
||||
?.PinType
|
||||
?.PinSubCategoryObject
|
||||
?.getName()
|
||||
@@ -232,7 +230,7 @@ export default function nodeTitle(entity) {
|
||||
return Utility.formatStringName(settingsObject.BlueprintElementType.getName())
|
||||
}
|
||||
if (settingsObject.Operation) {
|
||||
const match = settingsObject.Name.match(/PCGMetadata(\w+)Settings_\d+/)
|
||||
const match = settingsObject.Name?.valueOf().match(/PCGMetadata(\w+)Settings_\d+/)
|
||||
if (match) {
|
||||
return Utility.formatStringName(match[1] + ": " + settingsObject.Operation)
|
||||
}
|
||||
@@ -242,9 +240,9 @@ export default function nodeTitle(entity) {
|
||||
return settingsSubgraphObject.Graph.getName()
|
||||
}
|
||||
}
|
||||
let memberName = entity.FunctionReference?.MemberName
|
||||
let memberName = entity.FunctionReference?.MemberName?.valueOf()
|
||||
if (memberName) {
|
||||
const memberParent = entity.FunctionReference.MemberParent?.path ?? ""
|
||||
const memberParent = entity.FunctionReference.MemberParent?.path?.valueOf() ?? ""
|
||||
switch (memberName) {
|
||||
case "AddKey":
|
||||
let result = memberParent.match(sequencerScriptingNameRegex)
|
||||
@@ -379,7 +377,7 @@ export default function nodeTitle(entity) {
|
||||
return Utility.formatStringName(memberName)
|
||||
}
|
||||
if (entity.OpName) {
|
||||
switch (entity.OpName) {
|
||||
switch (entity.OpName.valueOf()) {
|
||||
case "Boolean::LogicAnd": return "Logic AND"
|
||||
case "Boolean::LogicEq": return "=="
|
||||
case "Boolean::LogicNEq": return "!="
|
||||
@@ -392,10 +390,10 @@ export default function nodeTitle(entity) {
|
||||
case "Numeric::DistancePos": return "Distance"
|
||||
case "Numeric::Mul": return String.fromCharCode(0x2a2f)
|
||||
}
|
||||
return Utility.formatStringName(entity.OpName).replaceAll("::", " ")
|
||||
return Utility.formatStringName(entity.OpName.valueOf()).replaceAll("::", " ")
|
||||
}
|
||||
if (entity.FunctionDisplayName) {
|
||||
return Utility.formatStringName(entity.FunctionDisplayName)
|
||||
return Utility.formatStringName(entity.FunctionDisplayName.valueOf())
|
||||
}
|
||||
if (entity.ObjectRef) {
|
||||
return entity.ObjectRef.getName()
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import Configuration from "../Configuration.js"
|
||||
import ArrayEntity from "../entity/ArrayEntity.js"
|
||||
import GuidEntity from "../entity/GuidEntity.js"
|
||||
import NaturalNumberEntity from "../entity/NaturalNumberEntity.js"
|
||||
import PinEntity from "../entity/PinEntity.js"
|
||||
import StringEntity from "../entity/StringEntity.js"
|
||||
|
||||
/** @param {PinEntity} pinEntity */
|
||||
const indexFromUpperCaseLetterName = pinEntity =>
|
||||
pinEntity.PinName.match(/^\s*([A-Z])\s*$/)?.[1]?.charCodeAt(0) - "A".charCodeAt(0)
|
||||
pinEntity.PinName?.valueOf().match(/^\s*([A-Z])\s*$/)?.[1]?.charCodeAt(0) - "A".charCodeAt(0)
|
||||
|
||||
/** @param {ObjectEntity} entity */
|
||||
export default function nodeVariadic(entity) {
|
||||
@@ -19,7 +22,7 @@ export default function nodeVariadic(entity) {
|
||||
switch (type) {
|
||||
case Configuration.paths.commutativeAssociativeBinaryOperator:
|
||||
case Configuration.paths.promotableOperator:
|
||||
name = entity.FunctionReference?.MemberName
|
||||
name = entity.FunctionReference?.MemberName?.valueOf()
|
||||
switch (name) {
|
||||
default:
|
||||
if (
|
||||
@@ -50,7 +53,7 @@ export default function nodeVariadic(entity) {
|
||||
pinIndexFromEntity ??= indexFromUpperCaseLetterName
|
||||
pinNameFromIndex ??= (index, min = -1, max = -1) => {
|
||||
const result = String.fromCharCode(index >= 0 ? index : max + "A".charCodeAt(0) + 1)
|
||||
entity.NumAdditionalInputs = pinEntities().length - 1
|
||||
entity.NumAdditionalInputs = new NaturalNumberEntity(pinEntities().length - 1)
|
||||
return result
|
||||
}
|
||||
break
|
||||
@@ -58,7 +61,7 @@ export default function nodeVariadic(entity) {
|
||||
break
|
||||
case Configuration.paths.multiGate:
|
||||
pinEntities ??= () => entity.getPinEntities().filter(pinEntity => pinEntity.isOutput())
|
||||
pinIndexFromEntity ??= pinEntity => Number(pinEntity.PinName.match(/^\s*Out[_\s]+(\d+)\s*$/i)?.[1])
|
||||
pinIndexFromEntity ??= pinEntity => Number(pinEntity.PinName?.valueOf().match(/^\s*Out[_\s]+(\d+)\s*$/i)?.[1])
|
||||
pinNameFromIndex ??= (index, min = -1, max = -1, newPin) =>
|
||||
`Out ${index >= 0 ? index : min > 0 ? "Out 0" : max + 1}`
|
||||
break
|
||||
@@ -74,26 +77,26 @@ export default function nodeVariadic(entity) {
|
||||
// break
|
||||
case Configuration.paths.switchInteger:
|
||||
pinEntities ??= () => entity.getPinEntities().filter(pinEntity => pinEntity.isOutput())
|
||||
pinIndexFromEntity ??= pinEntity => Number(pinEntity.PinName.match(/^\s*(\d+)\s*$/)?.[1])
|
||||
pinIndexFromEntity ??= pinEntity => Number(pinEntity.PinName?.valueOf().match(/^\s*(\d+)\s*$/)?.[1])
|
||||
pinNameFromIndex ??= (index, min = -1, max = -1, newPin) => (index < 0 ? max + 1 : index).toString()
|
||||
break
|
||||
case Configuration.paths.switchGameplayTag:
|
||||
pinNameFromIndex ??= (index, min = -1, max = -1, newPin) => {
|
||||
const result = `Case_${index >= 0 ? index : min > 0 ? "0" : max + 1}`
|
||||
entity.PinNames ??= []
|
||||
entity.PinNames.push(result)
|
||||
delete entity.PinTags[entity.PinTags.length - 1]
|
||||
entity.PinTags[entity.PinTags.length] = null
|
||||
entity.PinNames ??= new ArrayEntity()
|
||||
entity.PinNames.valueOf().push(new StringEntity(result))
|
||||
delete entity.PinTags.valueOf()[entity.PinTags.length - 1]
|
||||
entity.PinTags.valueOf()[entity.PinTags.length] = null
|
||||
return result
|
||||
}
|
||||
case Configuration.paths.switchName:
|
||||
case Configuration.paths.switchString:
|
||||
pinEntities ??= () => entity.getPinEntities().filter(pinEntity => pinEntity.isOutput())
|
||||
pinIndexFromEntity ??= pinEntity => Number(pinEntity.PinName.match(/^\s*Case[_\s]+(\d+)\s*$/i)?.[1])
|
||||
pinIndexFromEntity ??= pinEntity => Number(pinEntity.PinName.valueOf().match(/^\s*Case[_\s]+(\d+)\s*$/i)?.[1])
|
||||
pinNameFromIndex ??= (index, min = -1, max = -1, newPin) => {
|
||||
const result = `Case_${index >= 0 ? index : min > 0 ? "0" : max + 1}`
|
||||
entity.PinNames ??= []
|
||||
entity.PinNames.push(result)
|
||||
entity.PinNames ??= new ArrayEntity()
|
||||
entity.PinNames.valueOf().push(new StringEntity(result))
|
||||
return result
|
||||
}
|
||||
break
|
||||
@@ -138,8 +141,8 @@ export default function nodeVariadic(entity) {
|
||||
}
|
||||
)
|
||||
const newPin = new PinEntity(modelPin)
|
||||
newPin.PinId = GuidEntity.generateGuid()
|
||||
newPin.PinName = pinNameFromIndex(index, min, max, newPin)
|
||||
newPin.PinId = new GuidEntity()
|
||||
newPin.PinName = new StringEntity(pinNameFromIndex(index, min, max, newPin))
|
||||
newPin.PinToolTip = undefined
|
||||
entity.getCustomproperties(true).push(newPin)
|
||||
return newPin
|
||||
|
||||
@@ -54,15 +54,15 @@ const pinColorMaterial = css`120, 120, 120`
|
||||
|
||||
/** @param {PinEntity} entity */
|
||||
export default function pinColor(entity) {
|
||||
if (entity.PinType.PinCategory == "mask") {
|
||||
if (entity.PinType.PinCategory?.valueOf() == "mask") {
|
||||
const result = colors[entity.PinType.PinSubCategory]
|
||||
if (result) {
|
||||
return result
|
||||
}
|
||||
} else if (entity.PinType.PinCategory == "optional") {
|
||||
} else if (entity.PinType.PinCategory?.valueOf() == "optional") {
|
||||
return pinColorMaterial
|
||||
}
|
||||
return colors[entity.getType()]
|
||||
?? colors[entity.PinType.PinCategory.toLowerCase()]
|
||||
?? colors[entity.PinType.PinCategory?.valueOf().toLowerCase()]
|
||||
?? colors["default"]
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ const inputPinTemplates = {
|
||||
|
||||
/** @param {PinEntity} entity */
|
||||
export default function pinTemplate(entity) {
|
||||
if (entity.PinType.ContainerType?.toString() === "Array") {
|
||||
if (entity.PinType.ContainerType?.valueOf() === "Array") {
|
||||
return PinTemplate
|
||||
}
|
||||
if (entity.PinType.bIsReference && !entity.PinType.bIsConst) {
|
||||
if (entity.PinType.bIsReference?.valueOf() && !entity.PinType.bIsConst?.valueOf()) {
|
||||
return inputPinTemplates["MUTABLE_REFERENCE"]
|
||||
}
|
||||
if (entity.getType() === "exec") {
|
||||
|
||||
@@ -4,12 +4,12 @@ import Utility from "../Utility.js"
|
||||
export default function pinTitle(entity) {
|
||||
let result = entity.PinFriendlyName
|
||||
? entity.PinFriendlyName.toString()
|
||||
: Utility.formatStringName(entity.PinName ?? "")
|
||||
: Utility.formatStringName(entity.PinName?.valueOf() ?? "")
|
||||
let match
|
||||
if (
|
||||
entity.PinToolTip
|
||||
// Match up until the first \n excluded or last character
|
||||
&& (match = entity.PinToolTip.match(/\s*(.+?(?=\n)|.+\S)\s*/))
|
||||
&& (match = entity.PinToolTip?.valueOf().match(/\s*(.+?(?=\n)|.+\S)\s*/))
|
||||
) {
|
||||
if (match[1].toLowerCase() === result.toLowerCase()) {
|
||||
return match[1] // In case they match, then keep the case of the PinToolTip
|
||||
|
||||
@@ -2,11 +2,10 @@ import Configuration from "../Configuration.js"
|
||||
import Utility from "../Utility.js"
|
||||
import nodeTemplateClass from "../decoding/nodeTemplate.js"
|
||||
import nodeTitle from "../decoding/nodeTitle.js"
|
||||
import IdentifierEntity from "../entity/IdentifierEntity.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 SymbolEntity from "../entity/SymbolEntity.js"
|
||||
import NodeTemplate from "../template/node/NodeTemplate.js"
|
||||
import ISelectableDraggableElement from "./ISelectableDraggableElement.js"
|
||||
|
||||
@@ -28,7 +27,7 @@ export default class NodeElement extends ISelectableDraggableElement {
|
||||
advancedPinDisplay: {
|
||||
type: String,
|
||||
attribute: "data-advanced-display",
|
||||
converter: IdentifierEntity.attributeConverter,
|
||||
converter: SymbolEntity.attributeConverter,
|
||||
reflect: true,
|
||||
},
|
||||
enabledState: {
|
||||
@@ -86,7 +85,7 @@ export default class NodeElement extends ISelectableDraggableElement {
|
||||
/** @param {String} str */
|
||||
static fromSerializedObject(str) {
|
||||
str = str.trim()
|
||||
let entity = SerializerFactory.getSerializer(ObjectEntity).read(str)
|
||||
let entity = ObjectEntity.grammar.parse(str)
|
||||
return NodeElement.newObject(/** @type {ObjectEntity} */(entity))
|
||||
}
|
||||
|
||||
@@ -103,10 +102,13 @@ export default class NodeElement extends ISelectableDraggableElement {
|
||||
#redirectLinksAfterRename(name) {
|
||||
for (let sourcePinElement of this.getPinElements()) {
|
||||
for (let targetPinReference of sourcePinElement.getLinks()) {
|
||||
this.blueprint.getPin(targetPinReference).redirectLink(sourcePinElement, new PinReferenceEntity({
|
||||
objectName: name,
|
||||
pinGuid: sourcePinElement.entity.PinId,
|
||||
}))
|
||||
this.blueprint.getPin(targetPinReference).redirectLink(
|
||||
sourcePinElement,
|
||||
new PinReferenceEntity(
|
||||
name,
|
||||
sourcePinElement.entity.PinId,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,7 +119,7 @@ export default class NodeElement extends ISelectableDraggableElement {
|
||||
this.advancedPinDisplay = entity.AdvancedPinDisplay?.toString()
|
||||
this.enabledState = entity.EnabledState
|
||||
this.nodeDisplayName = nodeTitle(entity)
|
||||
this.pureFunction = entity.bIsPureFunc
|
||||
this.pureFunction = entity.bIsPureFunc?.valueOf()
|
||||
this.dragLinkObjects = []
|
||||
super.initialize(entity, template)
|
||||
this.#pins = this.template.createPinElements()
|
||||
@@ -223,7 +225,7 @@ export default class NodeElement extends ISelectableDraggableElement {
|
||||
}
|
||||
|
||||
setShowAdvancedPinDisplay(value) {
|
||||
this.entity.AdvancedPinDisplay = new IdentifierEntity(value ? "Shown" : "Hidden")
|
||||
this.entity.AdvancedPinDisplay = new SymbolEntity(value ? "Shown" : "Hidden")
|
||||
this.advancedPinDisplay = this.entity.AdvancedPinDisplay
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import Utility from "../Utility.js"
|
||||
import pinTemplate from "../decoding/pinTemplate.js"
|
||||
import ArrayEntity from "../entity/ArrayEntity.js"
|
||||
import GuidEntity from "../entity/GuidEntity.js"
|
||||
import LinearColorEntity from "../entity/LinearColorEntity.js"
|
||||
import PinEntity from "../entity/PinEntity.js"
|
||||
import PinReferenceEntity from "../entity/PinReferenceEntity.js"
|
||||
import StringEntity from "../entity/StringEntity.js"
|
||||
import PinTemplate from "../template/pin/PinTemplate.js"
|
||||
import ElementFactory from "./ElementFactory.js"
|
||||
import IElement from "./IElement.js"
|
||||
@@ -89,9 +91,9 @@ export default class PinElement extends IElement {
|
||||
nodeElement = undefined
|
||||
) {
|
||||
this.nodeElement = nodeElement
|
||||
this.advancedView = entity.bAdvancedView
|
||||
this.advancedView = entity.bAdvancedView?.valueOf()
|
||||
this.isLinked = false
|
||||
this.connectable = !entity.bNotConnectable
|
||||
this.connectable = !entity.bNotConnectable?.valueOf()
|
||||
super.initialize(entity, template)
|
||||
this.pinType = this.entity.getType()
|
||||
this.defaultValue = this.entity.getDefaultValue()
|
||||
@@ -106,7 +108,7 @@ export default class PinElement extends IElement {
|
||||
|
||||
createPinReference() {
|
||||
return new PinReferenceEntity({
|
||||
objectName: this.nodeElement.getNodeName(),
|
||||
objectName: new StringEntity(this.nodeElement.getNodeName()),
|
||||
pinGuid: this.getPinId(),
|
||||
})
|
||||
}
|
||||
@@ -118,7 +120,7 @@ export default class PinElement extends IElement {
|
||||
|
||||
/** @returns {String} */
|
||||
getPinName() {
|
||||
return this.entity.PinName
|
||||
return this.entity.PinName?.valueOf() ?? ""
|
||||
}
|
||||
|
||||
getPinDisplayName() {
|
||||
@@ -147,7 +149,7 @@ export default class PinElement extends IElement {
|
||||
}
|
||||
|
||||
getLinks() {
|
||||
return this.entity.LinkedTo ?? []
|
||||
return this.entity.LinkedTo?.valueOf() ?? []
|
||||
}
|
||||
|
||||
getDefaultValue(maybeCreate = false) {
|
||||
@@ -165,21 +167,23 @@ export default class PinElement extends IElement {
|
||||
|
||||
/** @param {IElement[]} nodesWhitelist */
|
||||
sanitizeLinks(nodesWhitelist = []) {
|
||||
this.entity.LinkedTo = this.entity.LinkedTo?.filter(pinReference => {
|
||||
let pin = this.blueprint.getPin(pinReference)
|
||||
if (pin) {
|
||||
if (nodesWhitelist.length && !nodesWhitelist.includes(pin.nodeElement)) {
|
||||
return false
|
||||
this.entity.LinkedTo = new ArrayEntity(
|
||||
this.entity.LinkedTo?.valueOf().filter(pinReference => {
|
||||
let pin = this.blueprint.getPin(pinReference)
|
||||
if (pin) {
|
||||
if (nodesWhitelist.length && !nodesWhitelist.includes(pin.nodeElement)) {
|
||||
return false
|
||||
}
|
||||
let link = this.blueprint.getLink(this, pin)
|
||||
if (!link) {
|
||||
link = /** @type {LinkElementConstructor} */(ElementFactory.getConstructor("ueb-link"))
|
||||
.newObject(this, pin)
|
||||
this.blueprint.addGraphElement(link)
|
||||
}
|
||||
}
|
||||
let link = this.blueprint.getLink(this, pin)
|
||||
if (!link) {
|
||||
link = /** @type {LinkElementConstructor} */(ElementFactory.getConstructor("ueb-link"))
|
||||
.newObject(this, pin)
|
||||
this.blueprint.addGraphElement(link)
|
||||
}
|
||||
}
|
||||
return pin
|
||||
})
|
||||
return pin
|
||||
})
|
||||
)
|
||||
this.isLinked = this.entity.isLinked()
|
||||
}
|
||||
|
||||
|
||||
37
js/entity/AlternativesEntity.js
Normal file
37
js/entity/AlternativesEntity.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import P from "parsernostrum"
|
||||
import IEntity from "./IEntity.js"
|
||||
|
||||
export default class AlternativesEntity extends IEntity {
|
||||
|
||||
/** @type {(typeof IEntity)[]} */
|
||||
static alternatives = []
|
||||
|
||||
static className() {
|
||||
let result = super.className()
|
||||
if (this.alternatives.length) {
|
||||
result += " (accepting: " + this.alternatives.map(v => v.className()).join(", ") + ")"
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
static createGrammar() {
|
||||
const grammars = this.alternatives.map(entity => entity.grammar)
|
||||
if (grammars.includes(this.unknownEntityGrammar)) {
|
||||
return this.unknownEntityGrammar
|
||||
}
|
||||
return P.alt(...grammars)
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {(typeof IEntity)[]} Types
|
||||
* @param {Types} types
|
||||
*/
|
||||
static accepting(...types) {
|
||||
const result = /** @type {typeof AlternativesEntity & { alternatives: Types }} */(
|
||||
this.asUniqueClass()
|
||||
)
|
||||
result.alternatives = types
|
||||
result.grammar = result.createGrammar()
|
||||
return result
|
||||
}
|
||||
}
|
||||
86
js/entity/ArrayEntity.js
Normal file
86
js/entity/ArrayEntity.js
Normal file
@@ -0,0 +1,86 @@
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
|
||||
/** @template {IEntity} T */
|
||||
export default class ArrayEntity extends IEntity {
|
||||
|
||||
/** @type {typeof IEntity} */
|
||||
static type
|
||||
static grammar = /** @type {P<ArrayEntity<IEntity>>} */(
|
||||
this.createGrammar()
|
||||
)
|
||||
|
||||
get length() {
|
||||
return this.values.length
|
||||
}
|
||||
|
||||
/** @param {T[]} values */
|
||||
constructor(values = []) {
|
||||
super()
|
||||
this.values = values
|
||||
}
|
||||
|
||||
/** @returns {P<ArrayEntity<IEntity>>} */
|
||||
static createGrammar(elementGrammar = this.type?.grammar ?? P.lazy(() => this.unknownEntityGrammar)) {
|
||||
return this.inlined
|
||||
? elementGrammar
|
||||
: P.seq(
|
||||
P.reg(/\(\s*/),
|
||||
elementGrammar.sepBy(Grammar.commaSeparation).opt(),
|
||||
P.reg(/\s*(,\s*)?\)/, 1),
|
||||
).map(([_0, values, trailing]) => {
|
||||
values = values instanceof Array ? values : []
|
||||
const result = new this(values)
|
||||
result.trailing = trailing !== undefined
|
||||
return result
|
||||
}).label(`ArrayEntity of ${this.type?.className() ?? "unknown values"}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {typeof IEntity} T
|
||||
* @param {T} type
|
||||
*/
|
||||
static of(type) {
|
||||
const result = /** @type {typeof ArrayEntity<ExtractType<T>> & {type: T, grammar: P<ArrayEntity<ExtractType<T>>> }} */(
|
||||
this.asUniqueClass()
|
||||
)
|
||||
result.type = type
|
||||
result.grammar = /** @type {P<ArrayEntity>} */(result.createGrammar())
|
||||
return result
|
||||
}
|
||||
|
||||
/** @param {IEntity} other */
|
||||
equals(other) {
|
||||
if (!(other instanceof ArrayEntity) || this.values.length !== other.values.length) {
|
||||
return false
|
||||
}
|
||||
for (let i = 0; i < this.values.length; ++i) {
|
||||
if (!this.values[i].equals(other.values[i])) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.values
|
||||
}
|
||||
|
||||
toString(
|
||||
insideString = false,
|
||||
indentation = "",
|
||||
Self = this.Self(),
|
||||
printKey = Self.printKey,
|
||||
wrap = Self.wrap,
|
||||
) {
|
||||
if (Self.inlined) {
|
||||
return super.toString.bind(this.values, insideString, indentation, Self, printKey, wrap)()
|
||||
}
|
||||
let result = this.values.map(v => v?.toString(insideString)).join(Self.attributeSeparator)
|
||||
if (this.trailing) {
|
||||
result += Self.attributeSeparator
|
||||
}
|
||||
return `(${result})`
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {{
|
||||
* type?: AttributeTypeDescription,
|
||||
* default?: T,
|
||||
* nullable?: Boolean,
|
||||
* ignored?: Boolean,
|
||||
* serialized?: Boolean,
|
||||
* expected?: Boolean,
|
||||
* inlined?: Boolean,
|
||||
* quoted?: Boolean,
|
||||
* silent?: Boolean,
|
||||
* uninitialized?: 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
|
||||
uninitialized: false, // Do not initialize with 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.uninitialized = source.uninitialized
|
||||
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]
|
||||
}
|
||||
}
|
||||
@@ -63,8 +63,8 @@ export default class BlueprintEntity extends ObjectEntity {
|
||||
this.ScriptVariables = entity.ScriptVariables
|
||||
}
|
||||
let scriptVariables = Utility.mergeArrays(
|
||||
this.ScriptVariables,
|
||||
entity.ScriptVariables,
|
||||
this.ScriptVariables.valueOf(),
|
||||
entity.ScriptVariables.valueOf(),
|
||||
(l, r) => l.OriginalChangeId.value == r.OriginalChangeId.value
|
||||
)
|
||||
if (scriptVariables.length === this.ScriptVariables.length) {
|
||||
|
||||
42
js/entity/BooleanEntity.js
Executable file
42
js/entity/BooleanEntity.js
Executable file
@@ -0,0 +1,42 @@
|
||||
import P from "parsernostrum"
|
||||
import IEntity from "./IEntity.js"
|
||||
|
||||
export default class BooleanEntity extends IEntity {
|
||||
|
||||
static grammar = /** @type {P<BooleanEntity>} */(
|
||||
P.regArray(/(true)|(True)|(false)|(False)/)
|
||||
.map(v => {
|
||||
const result = (v[1] ?? v[2]) ? new this(true) : new this(false)
|
||||
result.uppercase = (v[2] ?? v[4]) !== undefined
|
||||
return result
|
||||
})
|
||||
.label("BooleanEntity")
|
||||
)
|
||||
|
||||
#uppercase = true
|
||||
get uppercase() {
|
||||
return this.#uppercase
|
||||
}
|
||||
set uppercase(value) {
|
||||
this.#uppercase = value
|
||||
}
|
||||
|
||||
constructor(value = false) {
|
||||
super()
|
||||
this.value = value
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.value
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.value
|
||||
? this.#uppercase
|
||||
? "True"
|
||||
: "true"
|
||||
: this.#uppercase
|
||||
? "False"
|
||||
: "false"
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,19 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import P from "parsernostrum"
|
||||
import IntegerEntity from "./IntegerEntity.js"
|
||||
|
||||
export default class ByteEntity extends IntegerEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
value: new AttributeInfo({
|
||||
...super.attributes.value,
|
||||
predicate: v => v % 1 == 0 && v >= 0 && v < 1 << 8,
|
||||
}),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
static grammar = /** @type {P<ByteEntity>} */(
|
||||
P.numberByte.map(v => new this(v))
|
||||
)
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.numberByte.map(v => new this(v))
|
||||
get value() {
|
||||
return super.value
|
||||
}
|
||||
|
||||
constructor(values = 0) {
|
||||
super(values)
|
||||
set value(value) {
|
||||
value = Math.trunc(value)
|
||||
if (value >= 0 && value < 1 << 8) {
|
||||
super.value = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,15 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import P from "parsernostrum"
|
||||
import IEntity from "./IEntity.js"
|
||||
|
||||
export default class ColorChannelEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
value: AttributeInfo.createValue(0),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
static grammar = /** @type {P<ColorChannelEntity>} */(
|
||||
P.number.map(v => new this(v))
|
||||
)
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.number.map(value => new this(value))
|
||||
}
|
||||
|
||||
constructor(values = 0) {
|
||||
if (values.constructor !== Object) {
|
||||
// @ts-expect-error
|
||||
values = {
|
||||
value: values,
|
||||
}
|
||||
}
|
||||
super(values)
|
||||
/** @type {Number} */ this.value
|
||||
constructor(value = 0) {
|
||||
super()
|
||||
this.value = value
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
export default class ComputedType {
|
||||
|
||||
#f
|
||||
|
||||
/** @param {Function} f */
|
||||
constructor(f) {
|
||||
this.#f = f
|
||||
}
|
||||
|
||||
/** @param {IEntity} entity */
|
||||
compute(entity) {
|
||||
return this.#f(entity)
|
||||
}
|
||||
}
|
||||
23
js/entity/ComputedTypeEntity.js
Normal file
23
js/entity/ComputedTypeEntity.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import IEntity from "./IEntity.js"
|
||||
|
||||
export default class ComputedTypeEntity extends IEntity {
|
||||
|
||||
static grammar = undefined
|
||||
/** @type {(entity: IEntity) => typeof IEntity} */
|
||||
static f
|
||||
|
||||
/**
|
||||
* @template {typeof ComputedTypeEntity.f} T
|
||||
* @param {T} producer
|
||||
*/
|
||||
static from(producer) {
|
||||
const result = /** @type {(typeof ComputedTypeEntity) & { f: T }} */(this.asUniqueClass())
|
||||
result.f = producer
|
||||
return result
|
||||
}
|
||||
|
||||
/** @param {IEntity} entity */
|
||||
compute(entity) {
|
||||
return /** @type {typeof ComputedTypeEntity} */(this.Self()).f(entity)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import EnumEntity from "./EnumEntity.js"
|
||||
|
||||
export default class EnumDisplayValueEntity extends EnumEntity {
|
||||
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.reg(Grammar.Regex.InsideString).map(v => new this(v))
|
||||
}
|
||||
static grammar = /** @type {P<EnumDisplayValueEntity>} */(
|
||||
P.reg(Grammar.Regex.InsideString).map(v => new this(v))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import SymbolEntity from "./SymbolEntity.js"
|
||||
|
||||
export default class EnumEntity extends SymbolEntity {
|
||||
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.symbol.map(v => new this(v))
|
||||
}
|
||||
static grammar = /** @type {P<EnumEntity>} */(
|
||||
Grammar.symbol.map(v => new this(v))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,56 +1,43 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
import P from "parsernostrum"
|
||||
import InvariantTextEntity from "./InvariantTextEntity.js"
|
||||
import LocalizedTextEntity from "./LocalizedTextEntity.js"
|
||||
import Union from "./Union.js"
|
||||
import StringEntity from "./StringEntity.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
|
||||
export default class FormatTextEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
value: new AttributeInfo({
|
||||
type: [new Union(String, LocalizedTextEntity, InvariantTextEntity, FormatTextEntity)],
|
||||
default: [],
|
||||
}),
|
||||
lookbehind: /** @type {AttributeInfo<Union<String[]>>} */(new AttributeInfo({
|
||||
...super.attributes.lookbehind,
|
||||
default: new Union("LOCGEN_FORMAT_NAMED", "LOCGEN_FORMAT_ORDERED"),
|
||||
})),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.seq(
|
||||
Parsernostrum.reg(
|
||||
// Resulting regex: /(LOCGEN_FORMAT_NAMED|LOCGEN_FORMAT_ORDERED)\s*/
|
||||
new RegExp(`(${this.attributes.lookbehind.default.values.reduce((acc, cur) => acc + "|" + cur)})\\s*`),
|
||||
1
|
||||
),
|
||||
Grammar.grammarFor(this.attributes.value)
|
||||
static attributeSeparator = ", "
|
||||
static lookbehind = ["LOCGEN_FORMAT_NAMED", "LOCGEN_FORMAT_ORDERED"]
|
||||
static grammar = /** @type {P<FormatTextEntity>} */(
|
||||
P.lazy(() => P.seq(
|
||||
// Resulting regex: /(LOCGEN_FORMAT_NAMED|LOCGEN_FORMAT_ORDERED)\s*/
|
||||
P.reg(new RegExp(String.raw`(${this.lookbehind.join("|")})\s*\(\s*`), 1),
|
||||
P.alt(
|
||||
...[StringEntity, LocalizedTextEntity, InvariantTextEntity, FormatTextEntity].map(type => type.grammar)
|
||||
).sepBy(P.reg(/\s*\,\s*/)),
|
||||
P.reg(/\s*\)/)
|
||||
)
|
||||
.map(([lookbehind, values]) => {
|
||||
const result = new this({
|
||||
value: values,
|
||||
lookbehind,
|
||||
})
|
||||
const result = new this(values)
|
||||
result.lookbehind = lookbehind
|
||||
return result
|
||||
})
|
||||
}
|
||||
}))
|
||||
.label("FormatTextEntity")
|
||||
)
|
||||
|
||||
/** @param {(StringEntity | LocalizedTextEntity | InvariantTextEntity | FormatTextEntity)[]} values */
|
||||
constructor(values) {
|
||||
super(values)
|
||||
/** @type {(String | LocalizedTextEntity | InvariantTextEntity | FormatTextEntity)[]} */ this.value
|
||||
super()
|
||||
this.values = values
|
||||
}
|
||||
|
||||
toString() {
|
||||
const pattern = this.value?.[0]?.toString() // The pattern is always the first element of the array
|
||||
valueOf() {
|
||||
const pattern = this.values?.[0]?.valueOf() // The pattern is always the first element of the array
|
||||
if (!pattern) {
|
||||
return ""
|
||||
}
|
||||
const values = this.value.slice(1).map(v => v.toString())
|
||||
return this.lookbehind == "LOCGEN_FORMAT_NAMED"
|
||||
const values = this.values.slice(1).map(v => v?.valueOf())
|
||||
let result = this.lookbehind == "LOCGEN_FORMAT_NAMED"
|
||||
? pattern.replaceAll(/\{([a-zA-Z]\w*)\}/g, (substring, arg) => {
|
||||
const argLocation = values.indexOf(arg) + 1
|
||||
return argLocation > 0 && argLocation < values.length
|
||||
@@ -65,5 +52,20 @@ export default class FormatTextEntity extends IEntity {
|
||||
: substring
|
||||
})
|
||||
: ""
|
||||
return result
|
||||
}
|
||||
|
||||
toString(
|
||||
insideString = false,
|
||||
indentation = "",
|
||||
Self = this.Self(),
|
||||
printKey = Self.printKey,
|
||||
wrap = Self.wrap,
|
||||
) {
|
||||
const separator = Self.attributeSeparator
|
||||
return this.lookbehind + "("
|
||||
+ this.values.map(v => v.toString(insideString)).join(separator)
|
||||
+ (Self.trailing ? separator : "")
|
||||
+ ")"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
import P from "parsernostrum"
|
||||
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"
|
||||
import StringEntity from "./StringEntity.js"
|
||||
|
||||
export default class FunctionReferenceEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
MemberParent: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
MemberName: AttributeInfo.createType(String),
|
||||
MemberGuid: AttributeInfo.createType(GuidEntity),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.createEntityGrammar(this)
|
||||
MemberParent: ObjectReferenceEntity,
|
||||
MemberName: StringEntity,
|
||||
MemberGuid: GuidEntity,
|
||||
}
|
||||
static grammar = /** @type {P<FunctionReferenceEntity>} */(
|
||||
Grammar.createEntityGrammar(this, Grammar.commaSeparation, false, 0)
|
||||
)
|
||||
|
||||
constructor(values) {
|
||||
super(values)
|
||||
/** @type {ObjectReferenceEntity} */ this.MemberParent
|
||||
/** @type {String} */ this.MemberName
|
||||
/** @type {GuidEntity} */ this.MemberGuid
|
||||
/** @type {InstanceType<typeof FunctionReferenceEntity.attributes.MemberParent>} */ this.MemberParent
|
||||
/** @type {InstanceType<typeof FunctionReferenceEntity.attributes.MemberName>} */ this.MemberName
|
||||
/** @type {InstanceType<typeof FunctionReferenceEntity.attributes.MemberGuid>} */ this.MemberGuid
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
import P from "parsernostrum"
|
||||
|
||||
var crypto
|
||||
if (typeof window === "undefined") {
|
||||
@@ -11,39 +10,23 @@ if (typeof window === "undefined") {
|
||||
|
||||
export default class GuidEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
value: AttributeInfo.createValue(""),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
static grammar = /** @type {P<GuidEntity>} */(
|
||||
P.reg(/[0-9A-F]{32}/i).map(v => new this(v)).label("GuidEntity")
|
||||
)
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.guid.map(v => new this(v))
|
||||
}
|
||||
|
||||
static generateGuid(random = true) {
|
||||
static generateGuid() {
|
||||
let values = new Uint32Array(4)
|
||||
if (random === true) {
|
||||
crypto.getRandomValues(values)
|
||||
}
|
||||
crypto.getRandomValues(values)
|
||||
let guid = ""
|
||||
values.forEach(n => {
|
||||
guid += ("0".repeat(8) + n.toString(16).toUpperCase()).slice(-8)
|
||||
})
|
||||
return new GuidEntity({ value: guid })
|
||||
return guid
|
||||
}
|
||||
|
||||
constructor(values) {
|
||||
if (!values) {
|
||||
values = GuidEntity.generateGuid().value
|
||||
}
|
||||
if (values.constructor !== Object) {
|
||||
values = {
|
||||
value: values,
|
||||
}
|
||||
}
|
||||
super(values)
|
||||
/** @type {String} */ this.value
|
||||
constructor(value = GuidEntity.generateGuid()) {
|
||||
super()
|
||||
this.value = value
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
|
||||
@@ -1,169 +1,204 @@
|
||||
import Configuration from "../Configuration.js"
|
||||
import P from "parsernostrum"
|
||||
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"
|
||||
|
||||
/** @abstract */
|
||||
export default class IEntity extends Serializable {
|
||||
export default class IEntity {
|
||||
|
||||
/** @type {{ [attribute: String]: AttributeInfo }} */
|
||||
static attributes = {
|
||||
attributes: new AttributeInfo({
|
||||
ignored: true,
|
||||
}),
|
||||
lookbehind: new AttributeInfo({
|
||||
default: /** @type {String | Union<String[]>} */(""),
|
||||
ignored: true,
|
||||
uninitialized: true,
|
||||
}),
|
||||
/** @type {(v: String) => String} */
|
||||
static same = v => v
|
||||
/** @type {(entity: IEntity, serialized: String) => String} */
|
||||
static notWrapped = (entity, serialized) => serialized
|
||||
/** @type {(entity: IEntity, serialized: String) => String} */
|
||||
static defaultWrapped = (entity, serialized) => `${entity.#lookbehind}(${serialized})`
|
||||
static wrap = this.defaultWrapped
|
||||
static attributeSeparator = ","
|
||||
static keySeparator = "="
|
||||
/** @type {(k: String) => String} */
|
||||
static printKey = k => k
|
||||
/** @type {P<IEntity>} */
|
||||
static grammar = P.lazy(() => this.unknownEntity)
|
||||
/** @type {P<IEntity>} */
|
||||
static unknownEntityGrammar
|
||||
static unknownEntity
|
||||
/** @type {{ [key: String]: typeof IEntity }} */
|
||||
static attributes = {}
|
||||
/** @type {String | String[]} */
|
||||
static lookbehind = ""
|
||||
/** @type {(type: typeof IEntity) => InstanceType<typeof IEntity>} */
|
||||
static default
|
||||
static nullable = false
|
||||
static ignored = false // Never serialize or deserialize
|
||||
static serialized = false // Value is written and read as string
|
||||
static expected = false // Must be there
|
||||
static inlined = false // The key is a subobject or array and printed as inlined (A.B=123, A(0)=123)
|
||||
static quoted = false // Key is serialized with quotes
|
||||
static silent = false // Do not serialize if default
|
||||
static trailing = false // Add attribute separator after the last attribute when serializing
|
||||
|
||||
#trailing = this.Self().trailing
|
||||
get trailing() {
|
||||
return this.#trailing
|
||||
}
|
||||
set trailing(value) {
|
||||
this.#trailing = value
|
||||
}
|
||||
|
||||
#lookbehind = /** @type {String} */(this.Self().lookbehind)
|
||||
get lookbehind() {
|
||||
return this.#lookbehind.trim()
|
||||
}
|
||||
set lookbehind(value) {
|
||||
this.#lookbehind = value
|
||||
}
|
||||
|
||||
/** @type {String[]} */
|
||||
#_keys
|
||||
get _keys() {
|
||||
return this.#_keys
|
||||
#keys
|
||||
get keys() {
|
||||
return this.#keys ?? Object.keys(this)
|
||||
}
|
||||
set _keys(keys) {
|
||||
this.#_keys = keys
|
||||
set keys(value) {
|
||||
this.#keys = [... new Set(value)]
|
||||
}
|
||||
|
||||
constructor(values = {}, suppressWarns = false) {
|
||||
super()
|
||||
const Self = /** @type {typeof IEntity} */(this.constructor)
|
||||
/** @type {AttributeDeclarations?} */ this.attributes
|
||||
/** @type {String} */ this.lookbehind
|
||||
const valuesKeys = Object.keys(values)
|
||||
const attributesKeys = values.attributes
|
||||
? Utility.mergeArrays(Object.keys(values.attributes), Object.keys(Self.attributes))
|
||||
: Object.keys(Self.attributes)
|
||||
const allAttributesKeys = Utility.mergeArrays(valuesKeys, attributesKeys)
|
||||
for (const key of allAttributesKeys) {
|
||||
let value = values[key]
|
||||
if (!suppressWarns && !(key in values)) {
|
||||
if (!(key in Self.attributes) && !key.startsWith(Configuration.subObjectAttributeNamePrefix)) {
|
||||
const typeName = value instanceof Array ? `[${value[0]?.constructor.name}]` : value.constructor.name
|
||||
console.warn(
|
||||
`UEBlueprint: Attribute ${key} (of type ${typeName}) in the serialized data is not defined in ${Self.name}.attributes`
|
||||
)
|
||||
constructor(values = {}) {
|
||||
const attributes = this.Self().attributes
|
||||
const keys = Utility.mergeArrays(
|
||||
Object.keys(values),
|
||||
Object.entries(attributes).filter(([k, v]) => v.default !== undefined).map(([k, v]) => k)
|
||||
)
|
||||
for (const key of keys) {
|
||||
if (values[key] !== undefined) {
|
||||
if (values[key].constructor === Object) {
|
||||
// It is part of a nested key (words separated by ".")
|
||||
values[key] = new (
|
||||
attributes[key] !== undefined ? attributes[key] : IEntity.unknownEntity
|
||||
)(values[key])
|
||||
}
|
||||
}
|
||||
if (!(key in Self.attributes)) {
|
||||
// Remember attributeName can come from the values and be not defined in the attributes.
|
||||
// In that case just assign it and skip the rest.
|
||||
this[key] = value
|
||||
this[key] = values[key]
|
||||
continue
|
||||
}
|
||||
Self.attributes.lookbehind
|
||||
const predicate = AttributeInfo.getAttribute(values, key, "predicate", Self)
|
||||
const assignAttribute = !predicate
|
||||
? v => this[key] = v
|
||||
: v => {
|
||||
Object.defineProperties(this, {
|
||||
["#" + key]: {
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
},
|
||||
[key]: {
|
||||
enumerable: true,
|
||||
get() {
|
||||
return this["#" + key]
|
||||
},
|
||||
set(v) {
|
||||
if (!predicate(v)) {
|
||||
console.warn(
|
||||
`UEBlueprint: Tried to assign attribute ${key} to ${Self.name} not satisfying the predicate`
|
||||
)
|
||||
return
|
||||
}
|
||||
this["#" + key] = v
|
||||
}
|
||||
},
|
||||
})
|
||||
this[key] = v
|
||||
}
|
||||
|
||||
let defaultValue = AttributeInfo.getAttribute(values, key, "default", Self)
|
||||
if (defaultValue instanceof Function) {
|
||||
defaultValue = defaultValue(this)
|
||||
}
|
||||
let defaultType = AttributeInfo.getAttribute(values, key, "type", Self)
|
||||
if (defaultType instanceof ComputedType) {
|
||||
defaultType = defaultType.compute(this)
|
||||
}
|
||||
if (defaultType instanceof Array) {
|
||||
defaultType = Array
|
||||
}
|
||||
if (defaultType === undefined) {
|
||||
defaultType = Utility.getType(defaultValue)
|
||||
}
|
||||
|
||||
if (value !== undefined) {
|
||||
// Remember value can still be null
|
||||
if (
|
||||
value?.constructor === String
|
||||
&& AttributeInfo.getAttribute(values, key, "serialized", Self)
|
||||
&& defaultType !== String
|
||||
) {
|
||||
try {
|
||||
value = SerializerFactory
|
||||
.getSerializer(defaultType)
|
||||
.read(/** @type {String} */(value))
|
||||
} catch (e) {
|
||||
assignAttribute(value)
|
||||
continue
|
||||
}
|
||||
}
|
||||
assignAttribute(Utility.sanitize(value, /** @type {AttributeConstructor<Attribute>} */(defaultType)))
|
||||
continue // We have a value, need nothing more
|
||||
}
|
||||
if (defaultValue !== undefined && !AttributeInfo.getAttribute(values, key, "uninitialized", Self)) {
|
||||
assignAttribute(defaultValue)
|
||||
const attribute = attributes[key]
|
||||
if (attribute.default !== undefined) {
|
||||
this[key] = attribute.default(attribute)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {AttributeTypeDescription} attributeType */
|
||||
static defaultValueProviderFromType(attributeType) {
|
||||
if (attributeType === Boolean) {
|
||||
return false
|
||||
} else if (attributeType === Number) {
|
||||
return 0
|
||||
} else if (attributeType === BigInt) {
|
||||
return 0n
|
||||
} else if (attributeType === String) {
|
||||
return ""
|
||||
} else if (attributeType === Array || attributeType instanceof Array) {
|
||||
return () => []
|
||||
} else if (attributeType instanceof Union) {
|
||||
return this.defaultValueProviderFromType(attributeType.values[0])
|
||||
} else if (attributeType instanceof MirroredEntity) {
|
||||
return () => new MirroredEntity(attributeType.type, attributeType.getter)
|
||||
} else if (attributeType instanceof ComputedType) {
|
||||
return undefined
|
||||
} else {
|
||||
return () => new /** @type {AnyConstructor<Attribute>} */(attributeType)()
|
||||
static className() {
|
||||
let self = this
|
||||
while (!self.name) {
|
||||
self = Object.getPrototypeOf(self)
|
||||
}
|
||||
return self.name
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {new (...args: any) => any} C
|
||||
* @param {C} type
|
||||
* @returns {value is InstanceType<C>}
|
||||
* @protected
|
||||
* @template {typeof IEntity} T
|
||||
* @this {T}
|
||||
* @returns {T}
|
||||
*/
|
||||
static isValueOfType(value, type) {
|
||||
return value != null && (value instanceof type || value.constructor === type)
|
||||
static asUniqueClass() {
|
||||
if (this.name.length) {
|
||||
// @ts-expect-error
|
||||
return class extends this { }
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
static defineAttributes(object, attributes) {
|
||||
Object.defineProperty(object, "attributes", {
|
||||
writable: true,
|
||||
configurable: false,
|
||||
})
|
||||
object.attributes = attributes
|
||||
/**
|
||||
* @template {typeof IEntity} T
|
||||
* @this {T}
|
||||
* @param {String} value
|
||||
*/
|
||||
static withLookbehind(value) {
|
||||
const result = this.asUniqueClass()
|
||||
result.lookbehind = value
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {typeof IEntity} T
|
||||
* @this {T}
|
||||
*/
|
||||
static withDefault(value = /** @type {(type: T) => (InstanceType<T> | NullEntity)} */(type => new type())) {
|
||||
const result = this.asUniqueClass()
|
||||
result.default = value
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {typeof IEntity} T
|
||||
* @this {T}
|
||||
*/
|
||||
static flagNullable(value = true) {
|
||||
const result = this.asUniqueClass()
|
||||
result.nullable = value
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {typeof IEntity} T
|
||||
* @this {T}
|
||||
*/
|
||||
static flagSerialized(value = true) {
|
||||
const result = this.asUniqueClass()
|
||||
result.serialized = value
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {typeof IEntity} T
|
||||
* @this {T}
|
||||
*/
|
||||
static flagInlined(value = true) {
|
||||
const result = this.asUniqueClass()
|
||||
result.inlined = value
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {typeof IEntity} T
|
||||
* @this {T}
|
||||
*/
|
||||
static flagQuoted(value = true) {
|
||||
const result = this.asUniqueClass()
|
||||
result.quoted = value
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {typeof IEntity} T
|
||||
* @this {T}
|
||||
*/
|
||||
static flagSilent(value = true) {
|
||||
const result = this.asUniqueClass()
|
||||
result.silent = value
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {typeof IEntity} T
|
||||
* @this {InstanceType<T>}
|
||||
*/
|
||||
Self() {
|
||||
return /** @type {T} */(this.constructor)
|
||||
}
|
||||
|
||||
/** @param {String} key */
|
||||
showProperty(key) {
|
||||
/** @type {IEntity} */
|
||||
let value = this[key]
|
||||
const Self = this.Self()
|
||||
if (Self.silent && Self.default !== undefined) {
|
||||
if (Self["#default"] === undefined) {
|
||||
Self["#default"] = Self.default(Self)
|
||||
}
|
||||
const defaultValue = Self["#default"]
|
||||
return !value.equals(defaultValue)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,41 +228,96 @@ export default class IEntity extends Serializable {
|
||||
return this["#" + attribute]
|
||||
},
|
||||
set(v) {
|
||||
if (v == this["#" + attribute]) {
|
||||
return
|
||||
if (v != this["#" + attribute]) {
|
||||
callback(v)
|
||||
this["#" + attribute] = v
|
||||
}
|
||||
callback(v)
|
||||
this["#" + attribute] = v
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
getLookbehind() {
|
||||
let lookbehind = this.lookbehind ?? AttributeInfo.getAttribute(this, "lookbehind", "default")
|
||||
lookbehind = lookbehind instanceof Union ? lookbehind.values[0] : lookbehind
|
||||
return lookbehind
|
||||
}
|
||||
|
||||
unexpectedKeys() {
|
||||
return Object.keys(this).length - Object.keys(/** @type {typeof IEntity} */(this.constructor).attributes).length
|
||||
}
|
||||
|
||||
/** @param {IEntity} other */
|
||||
equals(other) {
|
||||
const thisKeys = Object.keys(this)
|
||||
const otherKeys = Object.keys(other)
|
||||
if (thisKeys.length != otherKeys.length) {
|
||||
if (!(other instanceof IEntity)) {
|
||||
return false
|
||||
}
|
||||
for (const key of thisKeys) {
|
||||
if (this[key] instanceof IEntity && !this[key].equals(other[key])) {
|
||||
return false
|
||||
} else if (!Utility.equals(this[key], other[key])) {
|
||||
const thisKeys = Object.keys(this)
|
||||
const otherKeys = Object.keys(other)
|
||||
if (
|
||||
thisKeys.length !== otherKeys.length
|
||||
|| this.lookbehind != other.lookbehind
|
||||
|| !(this instanceof other.constructor) && !(other instanceof this.constructor)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
for (let i = 0; i < thisKeys.length; ++i) {
|
||||
const k = thisKeys[i]
|
||||
if (!otherKeys.includes(k)) {
|
||||
return false
|
||||
}
|
||||
const a = this[k]
|
||||
const b = other[k]
|
||||
if (a instanceof IEntity) {
|
||||
if (!a.equals(b)) {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if (a !== b) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/** @this {IEntity | Array} */
|
||||
toString(
|
||||
insideString = false,
|
||||
indentation = "",
|
||||
Self = this.Self(),
|
||||
printKey = Self.printKey,
|
||||
wrap = Self.wrap,
|
||||
) {
|
||||
let result = ""
|
||||
let first = true
|
||||
const keys = this instanceof IEntity ? this.keys : Object.keys(this)
|
||||
for (const key of keys) {
|
||||
/** @type {IEntity} */
|
||||
const value = this[key]
|
||||
let keyValue = this instanceof Array ? `(${key})` : key
|
||||
if (value === undefined || this instanceof IEntity && !this.showProperty(key)) {
|
||||
continue
|
||||
}
|
||||
if (first) {
|
||||
first = false
|
||||
} else {
|
||||
result += Self.attributeSeparator
|
||||
}
|
||||
if (value.Self?.().inlined) {
|
||||
const inlinedPrintKey = value.Self().className() === "ArrayEntity"
|
||||
? k => printKey(`${keyValue}${k}`)
|
||||
: k => printKey(`${keyValue}.${k}`)
|
||||
result += value.toString(insideString, indentation, Self, inlinedPrintKey, Self.notWrapped)
|
||||
continue
|
||||
}
|
||||
keyValue = printKey(keyValue)
|
||||
if (keyValue.length) {
|
||||
if (Self.quoted) {
|
||||
keyValue = `"${keyValue}"`
|
||||
}
|
||||
result += (Self.attributeSeparator.includes("\n") ? indentation : "") + keyValue + Self.keySeparator
|
||||
}
|
||||
let serialization = value?.toString(insideString, indentation)
|
||||
if (Self.serialized) {
|
||||
serialization = `"${serialization.replaceAll(/(?<=(?:[^\\]|^)(?:\\\\)*?)"/, '\\"')}"`
|
||||
}
|
||||
result += serialization
|
||||
}
|
||||
if (this instanceof IEntity && this.trailing && result.length) {
|
||||
result += Self.attributeSeparator
|
||||
}
|
||||
return wrap(/** @type {IEntity} */(this), result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
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: AttributeInfo.createValue(""),
|
||||
}
|
||||
static attributeConverter = {
|
||||
fromAttribute: (value, type) => new IdentifierEntity(value),
|
||||
toAttribute: (value, type) => value.toString()
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.symbol.map(v => new this(v))
|
||||
}
|
||||
|
||||
constructor(values) {
|
||||
if (values.constructor !== Object) {
|
||||
values = {
|
||||
value: values,
|
||||
}
|
||||
}
|
||||
super(values)
|
||||
/** @type {String} */ this.value
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.value
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.value
|
||||
}
|
||||
}
|
||||
@@ -1,41 +1,40 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import P from "parsernostrum"
|
||||
import IEntity from "./IEntity.js"
|
||||
|
||||
export default class Integer64Entity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
value: new AttributeInfo({
|
||||
default: 0n,
|
||||
predicate: v => v >= -(1n << 63n) && v < 1n << 63n,
|
||||
}),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
static grammar = /** @type {P<Integer64Entity>} */(
|
||||
P.numberBigInteger.map(v => new this(v))
|
||||
)
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.numberBigInteger.map(v => new this(v))
|
||||
/** @type {bigint} */
|
||||
#value
|
||||
get value() {
|
||||
return this.#value
|
||||
}
|
||||
set value(value) {
|
||||
if (value >= -(1n << 63n) && value < 1n << 63n) {
|
||||
this.#value = value
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {BigInt | Number | Object} values */
|
||||
constructor(values = 0) {
|
||||
if (values.constructor !== Object) {
|
||||
values = {
|
||||
value: values,
|
||||
}
|
||||
}
|
||||
if (values.value === -0) {
|
||||
values.value = 0n
|
||||
}
|
||||
super(values)
|
||||
/** @type {BigInt} */ this.value
|
||||
/** @param {bigint | Number} value */
|
||||
constructor(value = 0n) {
|
||||
super()
|
||||
this.value = BigInt(value)
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.value
|
||||
}
|
||||
|
||||
toString() {
|
||||
toString(
|
||||
insideString = false,
|
||||
indentation = "",
|
||||
Self = this.Self(),
|
||||
printKey = Self.printKey,
|
||||
wrap = Self.wrap,
|
||||
) {
|
||||
return this.value.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +1,20 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
import P from "parsernostrum"
|
||||
import NumberEntity from "./NumberEntity.js"
|
||||
|
||||
export default class IntegerEntity extends IEntity {
|
||||
export default class IntegerEntity extends NumberEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
value: new AttributeInfo({
|
||||
default: 0,
|
||||
predicate: v => v % 1 == 0 && v > 1 << 31 && v < -(1 << 31),
|
||||
}),
|
||||
static grammar = /** @type {P<IntegerEntity>} */(
|
||||
P.numberInteger.map(v => new this(v))
|
||||
)
|
||||
|
||||
get value() {
|
||||
return super.value
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.numberInteger.map(v => new this(v))
|
||||
}
|
||||
|
||||
/** @param {Number | Object} values */
|
||||
constructor(values = 0) {
|
||||
if (values.constructor !== Object) {
|
||||
values = {
|
||||
value: values,
|
||||
}
|
||||
set value(value) {
|
||||
value = Math.trunc(value)
|
||||
if (value >= 1 << 31 && value < -(1 << 31)) {
|
||||
value = Math.floor(value)
|
||||
super.value = value
|
||||
}
|
||||
values.value = Math.floor(values.value)
|
||||
if (values.value === -0) {
|
||||
values.value = 0
|
||||
}
|
||||
super(values)
|
||||
/** @type {Number} */ this.value
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.value
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.value.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,33 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import P from "parsernostrum"
|
||||
import IEntity from "./IEntity.js"
|
||||
|
||||
export default class InvariantTextEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
value: AttributeInfo.createValue(""),
|
||||
lookbehind: new AttributeInfo({
|
||||
...super.attributes.lookbehind,
|
||||
default: "INVTEXT",
|
||||
}),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
static lookbehind = "INVTEXT"
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.alt(
|
||||
Parsernostrum.seq(
|
||||
Parsernostrum.reg(new RegExp(`${this.attributes.lookbehind.default}\\s*\\(`)),
|
||||
Grammar.grammarFor(this.attributes.value),
|
||||
Parsernostrum.reg(/\s*\)/)
|
||||
)
|
||||
.map(([_0, value, _2]) => value),
|
||||
Parsernostrum.reg(new RegExp(this.attributes.lookbehind.default)) // InvariantTextEntity can not have arguments
|
||||
.map(() => "")
|
||||
).map(value => new this(value))
|
||||
static grammar = /** @type {P<InvariantTextEntity>} */(
|
||||
P.alt(
|
||||
P.seq(
|
||||
P.reg(new RegExp(`${this.lookbehind}\\s*\\(`)),
|
||||
P.doubleQuotedString,
|
||||
P.reg(/\s*\)/)
|
||||
).map(([_0, value, _2]) => Number(value)),
|
||||
P.reg(new RegExp(this.lookbehind)).map(() => 0) // InvariantTextEntity can not have arguments
|
||||
)
|
||||
.map(value => new this(value))
|
||||
.label("InvariantTextEntity")
|
||||
)
|
||||
|
||||
constructor(value = "") {
|
||||
super()
|
||||
this.value = value
|
||||
}
|
||||
|
||||
constructor(values) {
|
||||
if (values.constructor !== Object) {
|
||||
values = {
|
||||
value: values,
|
||||
}
|
||||
}
|
||||
super(values)
|
||||
/** @type {String} */ this.value
|
||||
valueOf() {
|
||||
return this.value
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.value
|
||||
return this.lookbehind + "(" + this.value + ")"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +1,35 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import BooleanEntity from "./BooleanEntity.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
import IdentifierEntity from "./IdentifierEntity.js"
|
||||
import StringEntity from "./StringEntity.js"
|
||||
import SymbolEntity from "./SymbolEntity.js"
|
||||
|
||||
export default class KeyBindingEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
ActionName: AttributeInfo.createValue(""),
|
||||
bShift: AttributeInfo.createValue(false),
|
||||
bCtrl: AttributeInfo.createValue(false),
|
||||
bAlt: AttributeInfo.createValue(false),
|
||||
bCmd: AttributeInfo.createValue(false),
|
||||
Key: AttributeInfo.createType(IdentifierEntity),
|
||||
ActionName: StringEntity,
|
||||
bShift: BooleanEntity,
|
||||
bCtrl: BooleanEntity,
|
||||
bAlt: BooleanEntity,
|
||||
bCmd: BooleanEntity,
|
||||
Key: SymbolEntity,
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.alt(
|
||||
IdentifierEntity.grammar.map(identifier => new this({
|
||||
Key: identifier
|
||||
})),
|
||||
static grammar = /** @type {P<KeyBindingEntity>} */(
|
||||
P.alt(
|
||||
SymbolEntity.grammar.map(identifier => new this({ Key: identifier })),
|
||||
Grammar.createEntityGrammar(this)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
constructor(values = {}) {
|
||||
super(values, true)
|
||||
/** @type {String} */ this.ActionName
|
||||
/** @type {Boolean} */ this.bShift
|
||||
/** @type {Boolean} */ this.bCtrl
|
||||
/** @type {Boolean} */ this.bAlt
|
||||
/** @type {Boolean} */ this.bCmd
|
||||
/** @type {IdentifierEntity} */ this.Key
|
||||
constructor(values) {
|
||||
super(values)
|
||||
/** @type {InstanceType<typeof KeyBindingEntity.attributes.ActionName>} */ this.ActionName
|
||||
/** @type {InstanceType<typeof KeyBindingEntity.attributes.bShift>} */ this.bShift
|
||||
/** @type {InstanceType<typeof KeyBindingEntity.attributes.bCtrl>} */ this.bCtrl
|
||||
/** @type {InstanceType<typeof KeyBindingEntity.attributes.bAlt>} */ this.bAlt
|
||||
/** @type {InstanceType<typeof KeyBindingEntity.attributes.bCmd>} */ this.bCmd
|
||||
/** @type {InstanceType<typeof KeyBindingEntity.attributes.Key>} */ this.Key
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { css } from "lit"
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P 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"
|
||||
|
||||
@@ -10,42 +9,55 @@ export default class LinearColorEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
R: new AttributeInfo({
|
||||
type: ColorChannelEntity,
|
||||
default: () => new ColorChannelEntity(),
|
||||
expected: true,
|
||||
}),
|
||||
G: new AttributeInfo({
|
||||
type: ColorChannelEntity,
|
||||
default: () => new ColorChannelEntity(),
|
||||
expected: true,
|
||||
}),
|
||||
B: new AttributeInfo({
|
||||
type: ColorChannelEntity,
|
||||
default: () => new ColorChannelEntity(),
|
||||
expected: true,
|
||||
}),
|
||||
A: new AttributeInfo({
|
||||
type: ColorChannelEntity,
|
||||
default: () => new ColorChannelEntity(1),
|
||||
}),
|
||||
H: new AttributeInfo({
|
||||
type: ColorChannelEntity,
|
||||
default: () => new ColorChannelEntity(),
|
||||
ignored: true,
|
||||
}),
|
||||
S: new AttributeInfo({
|
||||
type: ColorChannelEntity,
|
||||
default: () => new ColorChannelEntity(),
|
||||
ignored: true,
|
||||
}),
|
||||
V: new AttributeInfo({
|
||||
type: ColorChannelEntity,
|
||||
default: () => new ColorChannelEntity(),
|
||||
ignored: true,
|
||||
}),
|
||||
R: ColorChannelEntity.withDefault(),
|
||||
G: ColorChannelEntity.withDefault(),
|
||||
B: ColorChannelEntity.withDefault(),
|
||||
A: ColorChannelEntity.withDefault(type => new type(1)),
|
||||
}
|
||||
static grammar = /** @type {P<LinearColorEntity>} */(
|
||||
Grammar.createEntityGrammar(this).label("LinearColorEntity")
|
||||
)
|
||||
|
||||
#H = new ColorChannelEntity()
|
||||
get H() {
|
||||
return this.#H
|
||||
}
|
||||
set H(value) {
|
||||
this.#H = value
|
||||
}
|
||||
|
||||
#S = new ColorChannelEntity()
|
||||
get S() {
|
||||
return this.#S
|
||||
}
|
||||
set S(value) {
|
||||
this.#S = value
|
||||
}
|
||||
|
||||
#V = new ColorChannelEntity()
|
||||
get V() {
|
||||
return this.#V
|
||||
}
|
||||
set V(value) {
|
||||
this.#V = value
|
||||
}
|
||||
|
||||
constructor(values) {
|
||||
super(values)
|
||||
if (values instanceof Array) {
|
||||
values = {
|
||||
R: values[0] ?? 0,
|
||||
G: values[1] ?? 0,
|
||||
B: values[2] ?? 0,
|
||||
A: values[3] ?? 1,
|
||||
}
|
||||
}
|
||||
/** @type {InstanceType<typeof LinearColorEntity.attributes.R>} */ this.R
|
||||
/** @type {InstanceType<typeof LinearColorEntity.attributes.G>} */ this.G
|
||||
/** @type {InstanceType<typeof LinearColorEntity.attributes.B>} */ this.B
|
||||
/** @type {InstanceType<typeof LinearColorEntity.attributes.A>} */ this.A
|
||||
this.#updateHSV()
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
/** @param {Number} x */
|
||||
static linearToSRGB(x) {
|
||||
@@ -75,22 +87,19 @@ export default class LinearColorEntity extends IEntity {
|
||||
|
||||
static getWhite() {
|
||||
return new LinearColorEntity({
|
||||
R: 1,
|
||||
G: 1,
|
||||
B: 1,
|
||||
R: new ColorChannelEntity(1),
|
||||
G: new ColorChannelEntity(1),
|
||||
B: new ColorChannelEntity(1),
|
||||
})
|
||||
}
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.createEntityGrammar(this, false)
|
||||
}
|
||||
|
||||
static getLinearColorFromHexGrammar() {
|
||||
return Parsernostrum.regArray(new RegExp(
|
||||
"#(" + Grammar.Regex.HexDigit.source + "{2})"
|
||||
+ "(" + Grammar.Regex.HexDigit.source + "{2})"
|
||||
+ "(" + Grammar.Regex.HexDigit.source + "{2})"
|
||||
+ "(" + Grammar.Regex.HexDigit.source + "{2})?"
|
||||
const hexDigit = /[0-9a-fA-F]/
|
||||
return P.regArray(new RegExp(
|
||||
"#(" + hexDigit.source + "{2})"
|
||||
+ "(" + hexDigit.source + "{2})"
|
||||
+ "(" + hexDigit.source + "{2})"
|
||||
+ "(" + hexDigit.source + "{2})?"
|
||||
)).map(([m, R, G, B, A]) => new this({
|
||||
R: parseInt(R, 16) / 255,
|
||||
G: parseInt(G, 16) / 255,
|
||||
@@ -100,12 +109,12 @@ export default class LinearColorEntity extends IEntity {
|
||||
}
|
||||
|
||||
static getLinearColorRGBListGrammar() {
|
||||
return Parsernostrum.seq(
|
||||
Parsernostrum.numberByte,
|
||||
return P.seq(
|
||||
P.numberByte,
|
||||
Grammar.commaSeparation,
|
||||
Parsernostrum.numberByte,
|
||||
P.numberByte,
|
||||
Grammar.commaSeparation,
|
||||
Parsernostrum.numberByte,
|
||||
P.numberByte,
|
||||
).map(([R, _1, G, _3, B]) => new this({
|
||||
R: R / 255,
|
||||
G: G / 255,
|
||||
@@ -115,23 +124,23 @@ export default class LinearColorEntity extends IEntity {
|
||||
}
|
||||
|
||||
static getLinearColorRGBGrammar() {
|
||||
return Parsernostrum.seq(
|
||||
Parsernostrum.reg(/rgb\s*\(\s*/),
|
||||
return P.seq(
|
||||
P.reg(/rgb\s*\(\s*/),
|
||||
this.getLinearColorRGBListGrammar(),
|
||||
Parsernostrum.reg(/\s*\)/)
|
||||
P.reg(/\s*\)/)
|
||||
).map(([_0, linearColor, _2]) => linearColor)
|
||||
}
|
||||
|
||||
static getLinearColorRGBAGrammar() {
|
||||
return Parsernostrum.seq(
|
||||
Parsernostrum.reg(/rgba\s*\(\s*/),
|
||||
return P.seq(
|
||||
P.reg(/rgba\s*\(\s*/),
|
||||
this.getLinearColorRGBListGrammar(),
|
||||
Parsernostrum.reg(/\s*\)/)
|
||||
P.reg(/\s*\)/)
|
||||
).map(([_0, linearColor, _2]) => linearColor)
|
||||
}
|
||||
|
||||
static getLinearColorFromAnyFormat() {
|
||||
return Parsernostrum.alt(
|
||||
return P.alt(
|
||||
this.getLinearColorFromHexGrammar(),
|
||||
this.getLinearColorRGBAGrammar(),
|
||||
this.getLinearColorRGBGrammar(),
|
||||
@@ -139,26 +148,6 @@ export default class LinearColorEntity extends IEntity {
|
||||
)
|
||||
}
|
||||
|
||||
constructor(values) {
|
||||
if (values instanceof Array) {
|
||||
values = {
|
||||
R: values[0] ?? 0,
|
||||
G: values[1] ?? 0,
|
||||
B: values[2] ?? 0,
|
||||
A: values[3] ?? 1,
|
||||
}
|
||||
}
|
||||
super(values)
|
||||
/** @type {ColorChannelEntity} */ this.R
|
||||
/** @type {ColorChannelEntity} */ this.G
|
||||
/** @type {ColorChannelEntity} */ this.B
|
||||
/** @type {ColorChannelEntity} */ this.A
|
||||
/** @type {ColorChannelEntity} */ this.H
|
||||
/** @type {ColorChannelEntity} */ this.S
|
||||
/** @type {ColorChannelEntity} */ this.V
|
||||
this.#updateHSV()
|
||||
}
|
||||
|
||||
#updateHSV() {
|
||||
const r = this.R.value
|
||||
const g = this.G.value
|
||||
@@ -324,8 +313,4 @@ export default class LinearColorEntity extends IEntity {
|
||||
toArray() {
|
||||
return [this.R.value, this.G.value, this.B.value, this.A.value]
|
||||
}
|
||||
|
||||
toString() {
|
||||
return Utility.printLinearColor(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P from "parsernostrum"
|
||||
import Utility from "../Utility.js"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import StringEntity from "./StringEntity.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
|
||||
export default class LocalizedTextEntity extends IEntity {
|
||||
|
||||
static attributeSeparator = ", "
|
||||
static printKey = k => ""
|
||||
static lookbehind = "NSLOCTEXT"
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
namespace: AttributeInfo.createValue(""),
|
||||
key: AttributeInfo.createValue(""),
|
||||
value: AttributeInfo.createValue(""),
|
||||
lookbehind: new AttributeInfo({
|
||||
...super.attributes.lookbehind,
|
||||
default: "NSLOCTEXT",
|
||||
}),
|
||||
namespace: StringEntity.withDefault(),
|
||||
key: StringEntity.withDefault(),
|
||||
value: StringEntity.withDefault(),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.regArray(new RegExp(
|
||||
String.raw`${this.attributes.lookbehind.default}\s*\(`
|
||||
+ String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*,`
|
||||
+ String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*,`
|
||||
+ String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*`
|
||||
+ String.raw`(?:,\s+)?`
|
||||
static grammar = /** @type {P<LocalizedTextEntity>} */(
|
||||
P.regArray(new RegExp(
|
||||
String.raw`${LocalizedTextEntity.lookbehind}\s*\(`
|
||||
+ String.raw`\s*"(?<namespace>${Grammar.Regex.InsideString.source})"\s*,`
|
||||
+ String.raw`\s*"(?<key>${Grammar.Regex.InsideString.source})"\s*,`
|
||||
+ String.raw`\s*"(?<value>${Grammar.Regex.InsideString.source})"\s*`
|
||||
+ String.raw`(?<trailing>,\s+)?`
|
||||
+ String.raw`\)`,
|
||||
"m"
|
||||
)).map(matchResult => new this({
|
||||
namespace: Utility.unescapeString(matchResult[1]),
|
||||
key: Utility.unescapeString(matchResult[2]),
|
||||
value: Utility.unescapeString(matchResult[3]),
|
||||
}))
|
||||
}
|
||||
)).map(({ groups: { namespace, key, value, trailing } }) => {
|
||||
return new this({
|
||||
namespace: new (this.attributes.namespace)(Utility.unescapeString(namespace)),
|
||||
key: new (this.attributes.namespace)(Utility.unescapeString(key)),
|
||||
value: new (this.attributes.namespace)(Utility.unescapeString(value)),
|
||||
trailing: trailing !== undefined,
|
||||
})
|
||||
}).label("LocalizedTextEntity")
|
||||
)
|
||||
|
||||
constructor(values) {
|
||||
constructor(values = {}) {
|
||||
super(values)
|
||||
/** @type {String} */ this.namespace
|
||||
/** @type {String} */ this.key
|
||||
/** @type {String} */ this.value
|
||||
/** @type {InstanceType<typeof LocalizedTextEntity.attributes.namespace>} */ this.namespace
|
||||
/** @type {InstanceType<typeof LocalizedTextEntity.attributes.key>} */ this.key
|
||||
/** @type {InstanceType<typeof LocalizedTextEntity.attributes.value>} */ this.value
|
||||
}
|
||||
|
||||
toString() {
|
||||
return Utility.capitalFirstLetter(this.value)
|
||||
valueOf() {
|
||||
return Utility.capitalFirstLetter(this.value.valueOf())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import P from "parsernostrum"
|
||||
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"
|
||||
@@ -8,30 +8,19 @@ export default class MacroGraphReferenceEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
MacroGraph: new AttributeInfo({
|
||||
type: ObjectReferenceEntity,
|
||||
default: () => new ObjectReferenceEntity(),
|
||||
}),
|
||||
GraphBlueprint: new AttributeInfo({
|
||||
type: ObjectReferenceEntity,
|
||||
default: () => new ObjectReferenceEntity(),
|
||||
}),
|
||||
GraphGuid: new AttributeInfo({
|
||||
type: GuidEntity,
|
||||
default: () => new GuidEntity(),
|
||||
}),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.createEntityGrammar(this)
|
||||
MacroGraph: ObjectReferenceEntity,
|
||||
GraphBlueprint: ObjectReferenceEntity,
|
||||
GraphGuid: GuidEntity,
|
||||
}
|
||||
static grammar = /** @type {P<MacroGraphReferenceEntity>} */(
|
||||
Grammar.createEntityGrammar(this)
|
||||
)
|
||||
|
||||
constructor(values) {
|
||||
super(values)
|
||||
/** @type {ObjectReferenceEntity} */ this.MacroGraph
|
||||
/** @type {ObjectReferenceEntity} */ this.GraphBlueprint
|
||||
/** @type {GuidEntity} */ this.GuidEntity
|
||||
/** @type {InstanceType<typeof MacroGraphReferenceEntity.attributes.MacroGraph>} */ this.MacroGraph
|
||||
/** @type {InstanceType<typeof MacroGraphReferenceEntity.attributes.GraphBlueprint>} */ this.GraphBlueprint
|
||||
/** @type {InstanceType<typeof MacroGraphReferenceEntity.attributes.GraphGuid>} */ this.GraphGuid
|
||||
}
|
||||
|
||||
getMacroName() {
|
||||
|
||||
@@ -1,36 +1,46 @@
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
|
||||
/** @template {Attribute} T */
|
||||
export default class MirroredEntity {
|
||||
/** @template {typeof IEntity} T */
|
||||
export default class MirroredEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
type: new AttributeInfo({
|
||||
ignored: true,
|
||||
}),
|
||||
getter: new AttributeInfo({
|
||||
ignored: true,
|
||||
}),
|
||||
}
|
||||
/** @type {typeof IEntity} */
|
||||
static type
|
||||
|
||||
/**
|
||||
* @param {ConstructorType<T>} type
|
||||
* @param {() => T} getter
|
||||
*/
|
||||
constructor(type, getter = null) {
|
||||
this.type = type
|
||||
/** @param {() => InstanceType<T>} getter */
|
||||
constructor(getter = null) {
|
||||
super()
|
||||
this.getter = getter
|
||||
}
|
||||
|
||||
get() {
|
||||
return this.getter()
|
||||
/**
|
||||
* @template {typeof IEntity} T
|
||||
* @param {T} type
|
||||
* @returns {typeof MirroredEntity<T>}
|
||||
*/
|
||||
static of(type) {
|
||||
const result = this.asUniqueClass()
|
||||
result.type = type
|
||||
result.grammar = result.getTargetType().grammar.map(v => new this())
|
||||
return result
|
||||
}
|
||||
|
||||
/** @returns {AttributeConstructor<Attribute>} */
|
||||
getTargetType() {
|
||||
/** @returns {typeof IEntity} */
|
||||
static getTargetType() {
|
||||
const result = this.type
|
||||
if (result instanceof MirroredEntity) {
|
||||
return result.getTargetType()
|
||||
if (result.prototype instanceof MirroredEntity) {
|
||||
return /** @type {typeof MirroredEntity} */(result).getTargetType()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
toString(
|
||||
insideString = false,
|
||||
indentation = "",
|
||||
Self = this.Self(),
|
||||
printKey = Self.printKey,
|
||||
wrap = Self.wrap,
|
||||
) {
|
||||
this.toString = this.getter.toString.bind(this.getter())
|
||||
return this.toString(insideString, indentation, Self, printKey, wrap)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import IntegerEntity from "./IntegerEntity.js"
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P from "parsernostrum"
|
||||
import Utility from "../Utility.js"
|
||||
import IntegerEntity from "./IntegerEntity.js"
|
||||
|
||||
export default class NaturalNumberEntity extends IntegerEntity {
|
||||
|
||||
static grammar = this.createGrammar()
|
||||
static grammar = /** @type {P<NaturalNumberEntity>} */(
|
||||
P.numberNatural.map(v => new this(v))
|
||||
)
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.numberNatural.map(v => new this(v))
|
||||
get value() {
|
||||
return super.value
|
||||
}
|
||||
|
||||
constructor(values = 0) {
|
||||
super(values)
|
||||
this.value = Math.round(Utility.clamp(this.value, 0))
|
||||
set value(value) {
|
||||
value = Math.round(Utility.clamp(this.value, 0))
|
||||
super.value = value
|
||||
}
|
||||
}
|
||||
|
||||
15
js/entity/NullEntity.js
Normal file
15
js/entity/NullEntity.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import P from "parsernostrum"
|
||||
import IEntity from "./IEntity.js"
|
||||
|
||||
export default class NullEntity extends IEntity {
|
||||
|
||||
static grammar = /** @type {P<NullEntity>} */(
|
||||
// @ts-expect-error
|
||||
P.reg(new RegExp(String.raw`\(${P.whitespaceInlineOpt.getParser().regexp.source}\)`))
|
||||
.map(v => new this())
|
||||
)
|
||||
|
||||
toString() {
|
||||
return "()"
|
||||
}
|
||||
}
|
||||
60
js/entity/NumberEntity.js
Executable file
60
js/entity/NumberEntity.js
Executable file
@@ -0,0 +1,60 @@
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
|
||||
export default class NumberEntity extends IEntity {
|
||||
|
||||
static numberRegexSource = String.raw`${Grammar.numberRegexSource}(?<=(?:\.(\d*0+))?)`
|
||||
static grammar = /** @type {P<NumberEntity>} */(
|
||||
P.regArray(
|
||||
new RegExp(`(?<n>${this.numberRegexSource})|(?<posInf>\\+?inf)|(?<negInf>-inf)`)
|
||||
).map(({ 2: precision, groups: { n, posInf, negInf } }) => new this(
|
||||
n ? Number(n) : posInf ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY,
|
||||
precision?.length
|
||||
)
|
||||
).label("NumberEntity")
|
||||
)
|
||||
|
||||
#precision = 0
|
||||
get precision() {
|
||||
return this.#precision
|
||||
}
|
||||
set precision(value) {
|
||||
this.#precision = value
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Number}
|
||||
*/
|
||||
_value
|
||||
get value() {
|
||||
return this._value
|
||||
}
|
||||
set value(value) {
|
||||
if (value === -0) {
|
||||
value = 0
|
||||
}
|
||||
this._value = value
|
||||
}
|
||||
|
||||
constructor(value = 0, precision = 0) {
|
||||
super()
|
||||
this.value = Number(value)
|
||||
this.#precision = Number(precision)
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.value
|
||||
}
|
||||
|
||||
toString() {
|
||||
if (this.value === Number.POSITIVE_INFINITY) {
|
||||
return "+inf"
|
||||
}
|
||||
if (this.value === Number.NEGATIVE_INFINITY) {
|
||||
return "-inf"
|
||||
}
|
||||
return this.#precision ? this.value.toFixed(this.#precision) : this.value.toString()
|
||||
}
|
||||
}
|
||||
@@ -1,212 +1,185 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P from "parsernostrum"
|
||||
import Configuration from "../Configuration.js"
|
||||
import Utility from "../Utility.js"
|
||||
import nodeColor from "../decoding/nodeColor.js"
|
||||
import nodeIcon from "../decoding/nodeIcon.js"
|
||||
import nodeVariadic from "../decoding/nodeVariadic.js"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import AlternativesEntity from "./AlternativesEntity.js"
|
||||
import ArrayEntity from "./ArrayEntity.js"
|
||||
import BooleanEntity from "./BooleanEntity.js"
|
||||
import FunctionReferenceEntity from "./FunctionReferenceEntity.js"
|
||||
import GuidEntity from "./GuidEntity.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 NaturalNumberEntity from "./NaturalNumberEntity.js"
|
||||
import NullEntity from "./NullEntity.js"
|
||||
import ObjectReferenceEntity from "./ObjectReferenceEntity.js"
|
||||
import PinEntity from "./PinEntity.js"
|
||||
import ScriptVariableEntity from "./ScriptVariableEntity.js"
|
||||
import StringEntity from "./StringEntity.js"
|
||||
import SymbolEntity from "./SymbolEntity.js"
|
||||
import Union from "./Union.js"
|
||||
import UnknownPinEntity from "./UnknownPinEntity.js"
|
||||
import VariableReferenceEntity from "./VariableReferenceEntity.js"
|
||||
import nodeVariadic from "../decoding/nodeVariadic.js"
|
||||
|
||||
export default class ObjectEntity extends IEntity {
|
||||
|
||||
static trailing = true
|
||||
|
||||
#exported = false
|
||||
get exported() {
|
||||
return this.#exported
|
||||
}
|
||||
set exported(value) {
|
||||
this.#exported = value
|
||||
}
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
isExported: new AttributeInfo({
|
||||
type: Boolean,
|
||||
ignored: true,
|
||||
}),
|
||||
Class: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
Name: AttributeInfo.createType(String),
|
||||
Archetype: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
ExportPath: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
ObjectRef: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
BlueprintElementType: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
BlueprintElementInstance: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
PinTags: new AttributeInfo({
|
||||
type: [null],
|
||||
inlined: true,
|
||||
}),
|
||||
PinNames: new AttributeInfo({
|
||||
type: [String],
|
||||
inlined: true,
|
||||
}),
|
||||
AxisKey: AttributeInfo.createType(SymbolEntity),
|
||||
InputAxisKey: AttributeInfo.createType(SymbolEntity),
|
||||
InputName: AttributeInfo.createType(String),
|
||||
InputType: AttributeInfo.createType(SymbolEntity),
|
||||
NumAdditionalInputs: AttributeInfo.createType(Number),
|
||||
bIsPureFunc: AttributeInfo.createType(Boolean),
|
||||
bIsConstFunc: AttributeInfo.createType(Boolean),
|
||||
bIsCaseSensitive: AttributeInfo.createType(Boolean),
|
||||
VariableReference: AttributeInfo.createType(VariableReferenceEntity),
|
||||
SelfContextInfo: AttributeInfo.createType(SymbolEntity),
|
||||
DelegatePropertyName: AttributeInfo.createType(String),
|
||||
DelegateOwnerClass: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
ComponentPropertyName: AttributeInfo.createType(String),
|
||||
EventReference: AttributeInfo.createType(FunctionReferenceEntity),
|
||||
FunctionReference: AttributeInfo.createType(FunctionReferenceEntity),
|
||||
FunctionScript: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
CustomFunctionName: AttributeInfo.createType(String),
|
||||
TargetType: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
MacroGraphReference: AttributeInfo.createType(MacroGraphReferenceEntity),
|
||||
Enum: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
EnumEntries: new AttributeInfo({
|
||||
type: [String],
|
||||
inlined: true,
|
||||
}),
|
||||
InputKey: AttributeInfo.createType(SymbolEntity),
|
||||
OpName: AttributeInfo.createType(String),
|
||||
CachedChangeId: AttributeInfo.createType(GuidEntity),
|
||||
FunctionDisplayName: AttributeInfo.createType(String),
|
||||
AddedPins: new AttributeInfo({
|
||||
type: [UnknownPinEntity],
|
||||
default: () => [],
|
||||
inlined: true,
|
||||
silent: true,
|
||||
}),
|
||||
ChangeId: AttributeInfo.createType(GuidEntity),
|
||||
MaterialFunction: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
bOverrideFunction: AttributeInfo.createType(Boolean),
|
||||
bInternalEvent: AttributeInfo.createType(Boolean),
|
||||
bConsumeInput: AttributeInfo.createType(Boolean),
|
||||
bExecuteWhenPaused: AttributeInfo.createType(Boolean),
|
||||
bOverrideParentBinding: AttributeInfo.createType(Boolean),
|
||||
bControl: AttributeInfo.createType(Boolean),
|
||||
bAlt: AttributeInfo.createType(Boolean),
|
||||
bShift: AttributeInfo.createType(Boolean),
|
||||
bCommand: AttributeInfo.createType(Boolean),
|
||||
CommentColor: AttributeInfo.createType(LinearColorEntity),
|
||||
bCommentBubbleVisible_InDetailsPanel: AttributeInfo.createType(Boolean),
|
||||
bColorCommentBubble: AttributeInfo.createType(Boolean),
|
||||
ProxyFactoryFunctionName: AttributeInfo.createType(String),
|
||||
ProxyFactoryClass: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
ProxyClass: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
StructType: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
MaterialExpression: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
MaterialExpressionComment: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
MoveMode: AttributeInfo.createType(SymbolEntity),
|
||||
TimelineName: AttributeInfo.createType(String),
|
||||
TimelineGuid: AttributeInfo.createType(GuidEntity),
|
||||
SizeX: AttributeInfo.createType(new MirroredEntity(IntegerEntity)),
|
||||
SizeY: AttributeInfo.createType(new MirroredEntity(IntegerEntity)),
|
||||
Text: AttributeInfo.createType(new MirroredEntity(String)),
|
||||
MaterialExpressionEditorX: AttributeInfo.createType(new MirroredEntity(IntegerEntity)),
|
||||
MaterialExpressionEditorY: AttributeInfo.createType(new MirroredEntity(IntegerEntity)),
|
||||
NodeTitle: AttributeInfo.createType(String),
|
||||
NodeTitleColor: AttributeInfo.createType(LinearColorEntity),
|
||||
PositionX: AttributeInfo.createType(new MirroredEntity(IntegerEntity)),
|
||||
PositionY: AttributeInfo.createType(new MirroredEntity(IntegerEntity)),
|
||||
SettingsInterface: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
PCGNode: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
HiGenGridSize: AttributeInfo.createType(SymbolEntity),
|
||||
Operation: AttributeInfo.createType(SymbolEntity),
|
||||
NodePosX: AttributeInfo.createType(IntegerEntity),
|
||||
NodePosY: AttributeInfo.createType(IntegerEntity),
|
||||
NodeHeight: AttributeInfo.createType(IntegerEntity),
|
||||
NodeWidth: AttributeInfo.createType(IntegerEntity),
|
||||
Graph: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
SubgraphInstance: AttributeInfo.createType(String),
|
||||
InputPins: new AttributeInfo({
|
||||
type: [ObjectReferenceEntity],
|
||||
inlined: true,
|
||||
}),
|
||||
OutputPins: new AttributeInfo({
|
||||
type: [ObjectReferenceEntity],
|
||||
inlined: true,
|
||||
}),
|
||||
bExposeToLibrary: AttributeInfo.createType(Boolean),
|
||||
bCanRenameNode: AttributeInfo.createType(Boolean),
|
||||
bCommentBubblePinned: AttributeInfo.createType(Boolean),
|
||||
bCommentBubbleVisible: AttributeInfo.createType(Boolean),
|
||||
NodeComment: AttributeInfo.createType(String),
|
||||
AdvancedPinDisplay: AttributeInfo.createType(IdentifierEntity),
|
||||
DelegateReference: AttributeInfo.createType(VariableReferenceEntity),
|
||||
EnabledState: AttributeInfo.createType(IdentifierEntity),
|
||||
NodeGuid: AttributeInfo.createType(GuidEntity),
|
||||
ErrorType: AttributeInfo.createType(IntegerEntity),
|
||||
ErrorMsg: AttributeInfo.createType(String),
|
||||
ScriptVariables: new AttributeInfo({
|
||||
type: [ScriptVariableEntity],
|
||||
inlined: true,
|
||||
}),
|
||||
Node: AttributeInfo.createType(new MirroredEntity(ObjectReferenceEntity)),
|
||||
ExportedNodes: AttributeInfo.createType(String),
|
||||
CustomProperties: AttributeInfo.createType([new Union(PinEntity, UnknownPinEntity)]),
|
||||
Class: ObjectReferenceEntity,
|
||||
Name: StringEntity,
|
||||
Archetype: ObjectReferenceEntity,
|
||||
ExportPath: ObjectReferenceEntity,
|
||||
ObjectRef: ObjectReferenceEntity,
|
||||
BlueprintElementType: ObjectReferenceEntity,
|
||||
BlueprintElementInstance: ObjectReferenceEntity,
|
||||
PinTags: ArrayEntity.of(NullEntity).flagInlined(),
|
||||
PinNames: ArrayEntity.of(StringEntity).flagInlined(),
|
||||
AxisKey: SymbolEntity,
|
||||
InputAxisKey: SymbolEntity,
|
||||
InputName: StringEntity,
|
||||
InputType: SymbolEntity,
|
||||
NumAdditionalInputs: NaturalNumberEntity,
|
||||
bIsPureFunc: BooleanEntity,
|
||||
bIsConstFunc: BooleanEntity,
|
||||
bIsCaseSensitive: BooleanEntity,
|
||||
VariableReference: VariableReferenceEntity,
|
||||
SelfContextInfo: SymbolEntity,
|
||||
DelegatePropertyName: StringEntity,
|
||||
DelegateOwnerClass: ObjectReferenceEntity,
|
||||
ComponentPropertyName: StringEntity,
|
||||
EventReference: FunctionReferenceEntity,
|
||||
FunctionReference: FunctionReferenceEntity,
|
||||
FunctionScript: ObjectReferenceEntity,
|
||||
CustomFunctionName: StringEntity,
|
||||
TargetType: ObjectReferenceEntity,
|
||||
MacroGraphReference: MacroGraphReferenceEntity,
|
||||
Enum: ObjectReferenceEntity,
|
||||
EnumEntries: ArrayEntity.of(StringEntity).flagInlined(),
|
||||
InputKey: SymbolEntity,
|
||||
OpName: StringEntity,
|
||||
CachedChangeId: GuidEntity,
|
||||
FunctionDisplayName: StringEntity,
|
||||
AddedPins: ArrayEntity.of(UnknownPinEntity).withDefault().flagInlined().flagSilent(),
|
||||
ChangeId: GuidEntity,
|
||||
MaterialFunction: ObjectReferenceEntity,
|
||||
bOverrideFunction: BooleanEntity,
|
||||
bInternalEvent: BooleanEntity,
|
||||
bConsumeInput: BooleanEntity,
|
||||
bExecuteWhenPaused: BooleanEntity,
|
||||
bOverrideParentBinding: BooleanEntity,
|
||||
bControl: BooleanEntity,
|
||||
bAlt: BooleanEntity,
|
||||
bShift: BooleanEntity,
|
||||
bCommand: BooleanEntity,
|
||||
CommentColor: LinearColorEntity,
|
||||
bCommentBubbleVisible_InDetailsPanel: BooleanEntity,
|
||||
bColorCommentBubble: BooleanEntity,
|
||||
ProxyFactoryFunctionName: StringEntity,
|
||||
ProxyFactoryClass: ObjectReferenceEntity,
|
||||
ProxyClass: ObjectReferenceEntity,
|
||||
StructType: ObjectReferenceEntity,
|
||||
MaterialExpression: ObjectReferenceEntity,
|
||||
MaterialExpressionComment: ObjectReferenceEntity,
|
||||
MoveMode: SymbolEntity,
|
||||
TimelineName: StringEntity,
|
||||
TimelineGuid: GuidEntity,
|
||||
SizeX: MirroredEntity.of(IntegerEntity),
|
||||
SizeY: MirroredEntity.of(IntegerEntity),
|
||||
Text: MirroredEntity.of(StringEntity),
|
||||
MaterialExpressionEditorX: MirroredEntity.of(IntegerEntity),
|
||||
MaterialExpressionEditorY: MirroredEntity.of(IntegerEntity),
|
||||
NodeTitle: StringEntity,
|
||||
NodeTitleColor: LinearColorEntity,
|
||||
PositionX: MirroredEntity.of(IntegerEntity),
|
||||
PositionY: MirroredEntity.of(IntegerEntity),
|
||||
SettingsInterface: ObjectReferenceEntity,
|
||||
PCGNode: ObjectReferenceEntity,
|
||||
HiGenGridSize: SymbolEntity,
|
||||
Operation: SymbolEntity,
|
||||
NodePosX: IntegerEntity,
|
||||
NodePosY: IntegerEntity,
|
||||
NodeHeight: IntegerEntity,
|
||||
NodeWidth: IntegerEntity,
|
||||
Graph: ObjectReferenceEntity,
|
||||
SubgraphInstance: StringEntity,
|
||||
InputPins: ArrayEntity.of(ObjectReferenceEntity).flagInlined(),
|
||||
OutputPins: ArrayEntity.of(ObjectReferenceEntity).flagInlined(),
|
||||
bExposeToLibrary: BooleanEntity,
|
||||
bCanRenameNode: BooleanEntity,
|
||||
bCommentBubblePinned: BooleanEntity,
|
||||
bCommentBubbleVisible: BooleanEntity,
|
||||
NodeComment: StringEntity,
|
||||
AdvancedPinDisplay: SymbolEntity,
|
||||
DelegateReference: VariableReferenceEntity,
|
||||
EnabledState: SymbolEntity,
|
||||
NodeGuid: GuidEntity,
|
||||
ErrorType: IntegerEntity,
|
||||
ErrorMsg: StringEntity,
|
||||
ScriptVariables: ArrayEntity.of(ScriptVariableEntity),
|
||||
Node: MirroredEntity.of(ObjectReferenceEntity),
|
||||
ExportedNodes: StringEntity,
|
||||
CustomProperties: ArrayEntity.of(AlternativesEntity.accepting(PinEntity, UnknownPinEntity)).withDefault().flagSilent(),
|
||||
}
|
||||
static nameRegex = /^(\w+?)(?:_(\d+))?$/
|
||||
static customPropertyGrammar = Parsernostrum.seq(
|
||||
Parsernostrum.reg(/CustomProperties\s+/),
|
||||
Grammar.grammarFor(
|
||||
undefined,
|
||||
this.attributes.CustomProperties.type[0]
|
||||
),
|
||||
static #nameRegex = /^(\w+?)(?:_(\d+))?$/
|
||||
static customPropertyGrammar = P.seq(
|
||||
P.reg(/CustomProperties\s+/),
|
||||
this.attributes.CustomProperties.type.grammar,
|
||||
).map(([_0, pin]) => values => {
|
||||
if (!values.CustomProperties) {
|
||||
values.CustomProperties = []
|
||||
}
|
||||
values.CustomProperties.push(pin)
|
||||
/** @type {InstanceType<typeof this.attributes.CustomProperties>} */(
|
||||
values.CustomProperties ??= new (this.attributes.CustomProperties)()
|
||||
).values.push(pin)
|
||||
})
|
||||
static inlinedArrayEntryGrammar = Parsernostrum.seq(
|
||||
Parsernostrum.alt(
|
||||
static inlinedArrayEntryGrammar = P.seq(
|
||||
P.alt(
|
||||
Grammar.symbolQuoted.map(v => [v, true]),
|
||||
Grammar.symbol.map(v => [v, false]),
|
||||
),
|
||||
Parsernostrum.reg(
|
||||
new RegExp(`\\s*\\(\\s*(\\d+)\\s*\\)\\s*\\=\\s*`),
|
||||
1
|
||||
).map(Number)
|
||||
P.reg(new RegExp(String.raw`\s*\(\s*(\d+)\s*\)\s*\=\s*`), 1).map(Number)
|
||||
)
|
||||
.chain(
|
||||
/** @param {[[String, Boolean], Number]} param */
|
||||
/** @param {[[keyof ObjectEntity.attributes, Boolean], Number]} param */
|
||||
([[symbol, quoted], index]) =>
|
||||
Grammar.grammarFor(this.attributes[symbol])
|
||||
.map(currentValue =>
|
||||
values => {
|
||||
(values[symbol] ??= [])[index] = currentValue
|
||||
Utility.objectSet(values, ["attributes", symbol, "quoted"], quoted)
|
||||
if (!this.attributes[symbol]?.inlined) {
|
||||
if (!values.attributes) {
|
||||
IEntity.defineAttributes(values, {})
|
||||
}
|
||||
Utility.objectSet(values, ["attributes", symbol, "type"], [currentValue.constructor])
|
||||
Utility.objectSet(values, ["attributes", symbol, "inlined"], true)
|
||||
this.attributes[symbol].grammar.map(currentValue =>
|
||||
values => {
|
||||
if (values[symbol] === undefined) {
|
||||
let arrayEntity = ArrayEntity
|
||||
if (quoted != arrayEntity.quoted) {
|
||||
arrayEntity = arrayEntity.flagQuoted(quoted)
|
||||
}
|
||||
if (!arrayEntity.inlined) {
|
||||
arrayEntity = arrayEntity.flagInlined()
|
||||
}
|
||||
values[symbol] = new arrayEntity()
|
||||
}
|
||||
)
|
||||
/** @type {ArrayEntity} */
|
||||
const target = values[symbol]
|
||||
target.values[index] = currentValue
|
||||
}
|
||||
)
|
||||
)
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createSubObjectGrammar() {
|
||||
return Parsernostrum.lazy(() => this.grammar)
|
||||
.map(object =>
|
||||
values => values[Configuration.subObjectAttributeNameFromEntity(object)] = object
|
||||
)
|
||||
}
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.seq(
|
||||
Parsernostrum.reg(/Begin +Object/),
|
||||
Parsernostrum.seq(
|
||||
Parsernostrum.whitespace,
|
||||
Parsernostrum.alt(
|
||||
static grammar = /** @type {P<ObjectEntity>} */(
|
||||
P.seq(
|
||||
P.reg(/Begin +Object/),
|
||||
P.seq(
|
||||
P.whitespace,
|
||||
P.alt(
|
||||
this.createSubObjectGrammar(),
|
||||
this.customPropertyGrammar,
|
||||
Grammar.createAttributeGrammar(this, Parsernostrum.reg(Grammar.Regex.MultipleWordsSymbols)),
|
||||
Grammar.createAttributeGrammar(this, P.reg(Grammar.Regex.MultipleWordsSymbols)),
|
||||
Grammar.createAttributeGrammar(this, Grammar.attributeNameQuoted, undefined, (obj, k, v) =>
|
||||
Utility.objectSet(obj, ["attributes", ...k, "quoted"], true)
|
||||
),
|
||||
@@ -215,119 +188,115 @@ export default class ObjectEntity extends IEntity {
|
||||
)
|
||||
.map(([_0, entry]) => entry)
|
||||
.many(),
|
||||
Parsernostrum.reg(/\s+End +Object/),
|
||||
P.reg(/\s+End +Object/),
|
||||
)
|
||||
.map(([_0, attributes, _2]) => {
|
||||
const values = {}
|
||||
attributes.forEach(attributeSetter => attributeSetter(values))
|
||||
return new this(values)
|
||||
})
|
||||
}
|
||||
|
||||
static getMultipleObjectsGrammar() {
|
||||
return Parsernostrum.seq(
|
||||
Parsernostrum.whitespaceOpt,
|
||||
.label("ObjectEntity")
|
||||
)
|
||||
static grammarMultipleObjects = P.seq(
|
||||
P.whitespaceOpt,
|
||||
this.grammar,
|
||||
P.seq(
|
||||
P.whitespace,
|
||||
this.grammar,
|
||||
Parsernostrum.seq(
|
||||
Parsernostrum.whitespace,
|
||||
this.grammar,
|
||||
)
|
||||
.map(([_0, object]) => object)
|
||||
.many(),
|
||||
Parsernostrum.whitespaceOpt
|
||||
)
|
||||
.map(([_0, first, remaining, _4]) => [first, ...remaining])
|
||||
.map(([_0, object]) => object)
|
||||
.many(),
|
||||
P.whitespaceOpt
|
||||
).map(([_0, first, remaining, _4]) => [first, ...remaining])
|
||||
|
||||
static createSubObjectGrammar() {
|
||||
return P.lazy(() => this.grammar)
|
||||
.map(object =>
|
||||
values => values[Configuration.subObjectAttributeNameFromEntity(object)] = object
|
||||
)
|
||||
}
|
||||
|
||||
/** @type {String} */
|
||||
#class
|
||||
|
||||
constructor(values = {}, suppressWarns = false) {
|
||||
if ("NodePosX" in values !== "NodePosY" in values) {
|
||||
constructor(values = {}) {
|
||||
if (("NodePosX" in values) !== ("NodePosY" in values)) {
|
||||
const entries = Object.entries(values)
|
||||
const [key, position] = "NodePosX" in values
|
||||
? ["NodePosY", Object.keys(values).indexOf("NodePosX") + 1]
|
||||
: ["NodePosX", Object.keys(values).indexOf("NodePosY")]
|
||||
const entry = [key, new (AttributeInfo.getAttribute(values, key, "type", ObjectEntity))()]
|
||||
entries.splice(position, 0, entry)
|
||||
entries.splice(position, 0, [key, new IntegerEntity(0)])
|
||||
values = Object.fromEntries(entries)
|
||||
}
|
||||
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
|
||||
super(values)
|
||||
|
||||
// Attributes
|
||||
/** @type {(PinEntity | UnknownPinEntity)[]} */ this.CustomProperties
|
||||
/** @type {Boolean} */ this.bIsPureFunc
|
||||
/** @type {Boolean} */ this.isExported
|
||||
/** @type {FunctionReferenceEntity} */ this.ComponentPropertyName
|
||||
/** @type {FunctionReferenceEntity} */ this.EventReference
|
||||
/** @type {FunctionReferenceEntity} */ this.FunctionReference
|
||||
/** @type {IdentifierEntity} */ this.AdvancedPinDisplay
|
||||
/** @type {IdentifierEntity} */ this.EnabledState
|
||||
/** @type {IntegerEntity} */ this.NodeHeight
|
||||
/** @type {IntegerEntity} */ this.NodePosX
|
||||
/** @type {IntegerEntity} */ this.NodePosY
|
||||
/** @type {IntegerEntity} */ this.NodeWidth
|
||||
/** @type {LinearColorEntity} */ this.CommentColor
|
||||
/** @type {LinearColorEntity} */ this.NodeTitleColor
|
||||
/** @type {MacroGraphReferenceEntity} */ this.MacroGraphReference
|
||||
/** @type {MirroredEntity} */ this.MaterialExpressionEditorX
|
||||
/** @type {MirroredEntity} */ this.MaterialExpressionEditorY
|
||||
/** @type {MirroredEntity} */ this.SizeX
|
||||
/** @type {MirroredEntity} */ this.SizeY
|
||||
/** @type {MirroredEntity} */ this.Text
|
||||
/** @type {MirroredEntity<IntegerEntity>} */ this.PositionX
|
||||
/** @type {MirroredEntity<IntegerEntity>} */ this.PositionY
|
||||
/** @type {MirroredEntity<ObjectReferenceEntity>} */ this.Node
|
||||
/** @type {null[]} */ this.PinTags
|
||||
/** @type {Number} */ this.NumAdditionalInputs
|
||||
/** @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.Enum
|
||||
/** @type {ObjectReferenceEntity} */ this.ExportPath
|
||||
/** @type {ObjectReferenceEntity} */ this.FunctionScript
|
||||
/** @type {ObjectReferenceEntity} */ this.Graph
|
||||
/** @type {ObjectReferenceEntity} */ this.MaterialExpression
|
||||
/** @type {ObjectReferenceEntity} */ this.MaterialExpressionComment
|
||||
/** @type {ObjectReferenceEntity} */ this.MaterialFunction
|
||||
/** @type {ObjectReferenceEntity} */ this.ObjectRef
|
||||
/** @type {ObjectReferenceEntity} */ this.PCGNode
|
||||
/** @type {ObjectReferenceEntity} */ this.SettingsInterface
|
||||
/** @type {ObjectReferenceEntity} */ this.StructType
|
||||
/** @type {ObjectReferenceEntity} */ this.TargetType
|
||||
/** @type {ScriptVariableEntity[]} */ this.ScriptVariables
|
||||
/** @type {String[]} */ this.EnumEntries
|
||||
/** @type {String[]} */ this.PinNames
|
||||
/** @type {String} */ this.CustomFunctionName
|
||||
/** @type {String} */ this.DelegatePropertyName
|
||||
/** @type {String} */ this.ExportedNodes
|
||||
/** @type {String} */ this.FunctionDisplayName
|
||||
/** @type {String} */ this.InputName
|
||||
/** @type {String} */ this.Name
|
||||
/** @type {String} */ this.NodeComment
|
||||
/** @type {String} */ this.NodeTitle
|
||||
/** @type {String} */ this.Operation
|
||||
/** @type {String} */ this.OpName
|
||||
/** @type {String} */ this.ProxyFactoryFunctionName
|
||||
/** @type {String} */ this.SubgraphInstance
|
||||
/** @type {String} */ this.Text
|
||||
/** @type {SymbolEntity} */ this.AxisKey
|
||||
/** @type {SymbolEntity} */ this.HiGenGridSize
|
||||
/** @type {SymbolEntity} */ this.InputAxisKey
|
||||
/** @type {SymbolEntity} */ this.InputKey
|
||||
/** @type {SymbolEntity} */ this.InputType
|
||||
/** @type {UnknownPinEntity[]} */ this.AddedPins
|
||||
/** @type {VariableReferenceEntity} */ this.DelegateReference
|
||||
/** @type {VariableReferenceEntity} */ this.VariableReference
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.AddedPins>} */ this.AddedPins
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.AdvancedPinDisplay>} */ this.AdvancedPinDisplay
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.Archetype>} */ this.Archetype
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.AxisKey>} */ this.AxisKey
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.bIsPureFunc>} */ this.bIsPureFunc
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.BlueprintElementInstance>} */ this.BlueprintElementInstance
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.BlueprintElementType>} */ this.BlueprintElementType
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.Class>} */ this.Class
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.CommentColor>} */ this.CommentColor
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.ComponentPropertyName>} */ this.ComponentPropertyName
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.CustomFunctionName>} */ this.CustomFunctionName
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.CustomProperties>} */ this.CustomProperties
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.DelegatePropertyName>} */ this.DelegatePropertyName
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.DelegateReference>} */ this.DelegateReference
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.EnabledState>} */ this.EnabledState
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.Enum>} */ this.Enum
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.EnumEntries>} */ this.EnumEntries
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.EventReference>} */ this.EventReference
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.ExportedNodes>} */ this.ExportedNodes
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.ExportPath>} */ this.ExportPath
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.FunctionDisplayName>} */ this.FunctionDisplayName
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.FunctionReference>} */ this.FunctionReference
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.FunctionScript>} */ this.FunctionScript
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.Graph>} */ this.Graph
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.HiGenGridSize>} */ this.HiGenGridSize
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.InputAxisKey>} */ this.InputAxisKey
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.InputKey>} */ this.InputKey
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.InputName>} */ this.InputName
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.InputPins>} */ this.InputPins
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.InputType>} */ this.InputType
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.MacroGraphReference>} */ this.MacroGraphReference
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.MaterialExpression>} */ this.MaterialExpression
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.MaterialExpressionComment>} */ this.MaterialExpressionComment
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.MaterialExpressionEditorX>} */ this.MaterialExpressionEditorX
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.MaterialExpressionEditorY>} */ this.MaterialExpressionEditorY
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.MaterialFunction>} */ this.MaterialFunction
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.Name>} */ this.Name
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.Node>} */ this.Node
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.NodeComment>} */ this.NodeComment
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.NodeHeight>} */ this.NodeHeight
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.NodePosX>} */ this.NodePosX
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.NodePosY>} */ this.NodePosY
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.NodeTitle>} */ this.NodeTitle
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.NodeTitleColor>} */ this.NodeTitleColor
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.NodeWidth>} */ this.NodeWidth
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.NumAdditionalInputs>} */ this.NumAdditionalInputs
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.ObjectRef>} */ this.ObjectRef
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.Operation>} */ this.Operation
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.OpName>} */ this.OpName
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.OutputPins>} */ this.OutputPins
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.PCGNode>} */ this.PCGNode
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.PinTags>} */ this.PinTags
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.PinNames>} */ this.PinNames
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.PositionX>} */ this.PositionX
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.PositionY>} */ this.PositionY
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.ProxyFactoryFunctionName>} */ this.ProxyFactoryFunctionName
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.ScriptVariables>} */ this.ScriptVariables
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.SettingsInterface>} */ this.SettingsInterface
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.SizeX>} */ this.SizeX
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.SizeY>} */ this.SizeY
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.StructType>} */ this.StructType
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.SubgraphInstance>} */ this.SubgraphInstance
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.TargetType>} */ this.TargetType
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.Text>} */ this.Text
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.Text>} */ this.Text
|
||||
/** @type {InstanceType<typeof ObjectEntity.attributes.VariableReference>} */ this.VariableReference
|
||||
|
||||
// Legacy nodes pins
|
||||
if (this["Pins"] instanceof Array) {
|
||||
@@ -337,7 +306,7 @@ export default class ObjectEntity extends IEntity {
|
||||
const pinObject = this[Configuration.subObjectAttributeNameFromReference(objectReference, true)]
|
||||
if (pinObject) {
|
||||
const pinEntity = PinEntity.fromLegacyObject(pinObject)
|
||||
pinEntity.LinkedTo = []
|
||||
pinEntity.LinkedTo = new (PinEntity.attributes.LinkedTo)()
|
||||
this.getCustomproperties(true).push(pinEntity)
|
||||
Utility.objectSet(this, ["attributes", "CustomProperties", "ignored"], true)
|
||||
}
|
||||
@@ -356,22 +325,14 @@ export default class ObjectEntity extends IEntity {
|
||||
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))
|
||||
this.getPinEntities().find(pin => pin.PinName.toString() === 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)
|
||||
Utility.objectSet(obj, ["attributes", "R", "default"], false)
|
||||
Utility.objectSet(obj, ["attributes", "R", "silent"], true)
|
||||
Utility.objectSet(obj, ["attributes", "G", "default"], false)
|
||||
Utility.objectSet(obj, ["attributes", "G", "silent"], true)
|
||||
Utility.objectSet(obj, ["attributes", "B", "default"], false)
|
||||
Utility.objectSet(obj, ["attributes", "B", "silent"], true)
|
||||
Utility.objectSet(obj, ["attributes", "A", "default"], false)
|
||||
Utility.objectSet(obj, ["attributes", "A", "silent"], true)
|
||||
obj._keys = [...Configuration.rgba, ...Object.keys(obj).filter(k => !Configuration.rgba.includes(k))]
|
||||
const silentBool = MirroredEntity.of(BooleanEntity).withDefault().flagSilent()
|
||||
obj["R"] = new silentBool(() => rgbaPins[0].DefaultValue)
|
||||
obj["G"] = new silentBool(() => rgbaPins[1].DefaultValue)
|
||||
obj["B"] = new silentBool(() => rgbaPins[2].DefaultValue)
|
||||
obj["A"] = new silentBool(() => rgbaPins[3].DefaultValue)
|
||||
obj.keys = [...Configuration.rgba, ...super.keys.filter(k => !Configuration.rgba.includes(k))]
|
||||
}
|
||||
}
|
||||
/** @type {ObjectEntity} */
|
||||
@@ -383,15 +344,15 @@ export default class ObjectEntity extends IEntity {
|
||||
/** @param {ObjectEntity} obj */
|
||||
obj => {
|
||||
if (obj.Node !== undefined) {
|
||||
const nodeRef = obj.Node.get()
|
||||
const nodeRef = obj.Node.getter()
|
||||
if (
|
||||
nodeRef.type === this.PCGNode.type
|
||||
&& nodeRef.path === `${this.Name}.${this.PCGNode.path}`
|
||||
) {
|
||||
obj.Node.getter = () => new ObjectReferenceEntity({
|
||||
type: this.PCGNode.type,
|
||||
path: `${this.Name}.${this.PCGNode.path}`,
|
||||
})
|
||||
obj.Node.getter = () => new ObjectReferenceEntity(
|
||||
this.PCGNode.type,
|
||||
`${this.Name}.${this.PCGNode.path}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -400,7 +361,7 @@ export default class ObjectEntity extends IEntity {
|
||||
}
|
||||
let inputIndex = 0
|
||||
let outputIndex = 0
|
||||
this.CustomProperties?.forEach((pinEntity, i) => {
|
||||
this.getCustomproperties().forEach((pinEntity, i) => {
|
||||
pinEntity.objectEntity = this
|
||||
pinEntity.pinIndex = pinEntity.isInput()
|
||||
? inputIndex++
|
||||
@@ -441,12 +402,12 @@ export default class ObjectEntity extends IEntity {
|
||||
if (dropCounter) {
|
||||
return this.getNameAndCounter()[0]
|
||||
}
|
||||
return this.Name
|
||||
return this.Name.valueOf()
|
||||
}
|
||||
|
||||
/** @returns {[String, Number]} */
|
||||
getNameAndCounter() {
|
||||
const result = this.getObjectName().match(ObjectEntity.nameRegex)
|
||||
const result = this.getObjectName().match(ObjectEntity.#nameRegex)
|
||||
let name = ""
|
||||
let counter = null
|
||||
return result
|
||||
@@ -509,10 +470,7 @@ export default class ObjectEntity extends IEntity {
|
||||
}
|
||||
|
||||
getCustomproperties(canCreate = false) {
|
||||
if (canCreate && !this.CustomProperties) {
|
||||
this.CustomProperties = []
|
||||
}
|
||||
return this.CustomProperties ?? []
|
||||
return this.CustomProperties.values
|
||||
}
|
||||
|
||||
/** @returns {PinEntity[]} */
|
||||
@@ -629,7 +587,7 @@ export default class ObjectEntity extends IEntity {
|
||||
}
|
||||
|
||||
getDelegatePin() {
|
||||
return this.getCustomproperties().find(pin => pin.PinType.PinCategory === "delegate")
|
||||
return this.getCustomproperties().find(pin => pin.PinType.PinCategory.toString() === "delegate")
|
||||
}
|
||||
|
||||
nodeColor() {
|
||||
@@ -643,4 +601,46 @@ export default class ObjectEntity extends IEntity {
|
||||
additionalPinInserter() {
|
||||
return nodeVariadic(this)
|
||||
}
|
||||
|
||||
/** @param {String} key */
|
||||
showProperty(key) {
|
||||
switch (key) {
|
||||
case "Class":
|
||||
case "Name":
|
||||
case "Archetype":
|
||||
case "ExportPath":
|
||||
case "CustomProperties":
|
||||
// Serielized separately, check doWrite()
|
||||
return false
|
||||
}
|
||||
return super.showProperty(key)
|
||||
}
|
||||
|
||||
toString(
|
||||
insideString = false,
|
||||
indentation = "",
|
||||
Self = this.Self(),
|
||||
printKey = Self.printKey,
|
||||
wrap = Self.wrap,
|
||||
) {
|
||||
const moreIndentation = indentation + Configuration.indentation
|
||||
let result = indentation + "Begin Object"
|
||||
+ (this.Class?.type || this.Class?.path ? ` Class=${this.Class.toString(insideString)}` : "")
|
||||
+ (this.Name ? ` Name=${this.Name.toString(insideString)}` : "")
|
||||
+ (this.Archetype ? ` Archetype=${this.Archetype.toString(insideString)}` : "")
|
||||
+ (this.ExportPath?.type || this.ExportPath?.path ? ` ExportPath=${this.ExportPath.toString(insideString)}` : "")
|
||||
+ "\n"
|
||||
+ super.toString(insideString, moreIndentation, Self, printKey, wrap)
|
||||
+ (!this.CustomProperties.Self().ignored
|
||||
? this.getCustomproperties().map(pin =>
|
||||
moreIndentation
|
||||
+ printKey("CustomProperties ")
|
||||
+ pin.toString(insideString)
|
||||
+ this.Self().attributeSeparator
|
||||
).join("")
|
||||
: ""
|
||||
)
|
||||
+ indentation + "End Object"
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,80 +1,105 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P 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 ObjectReferenceEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
type: new AttributeInfo({
|
||||
default: "",
|
||||
serialized: true,
|
||||
}),
|
||||
path: new AttributeInfo({
|
||||
default: "",
|
||||
serialized: true,
|
||||
}),
|
||||
_full: new AttributeInfo({
|
||||
ignored: true,
|
||||
}),
|
||||
}
|
||||
static quoted = Parsernostrum.regArray(new RegExp(
|
||||
static #quotedParser = P.regArray(new RegExp(
|
||||
`'"(${Grammar.Regex.InsideString.source})"'`
|
||||
+ "|"
|
||||
+ `'(${Grammar.Regex.InsideSingleQuotedString.source})'`
|
||||
)).map(([_0, a, b]) => a ?? b)
|
||||
static path = this.quoted.getParser().parser.regexp.source + "|" + Grammar.Regex.Path.source
|
||||
static typeReference = Parsernostrum.reg(
|
||||
static typeReference = P.reg(
|
||||
// @ts-expect-error
|
||||
new RegExp(Grammar.Regex.Path.source + "|" + Grammar.symbol.getParser().regexp.source)
|
||||
)
|
||||
static fullReferenceGrammar = Parsernostrum.regArray(
|
||||
static fullReferenceGrammar = P.regArray(
|
||||
new RegExp(
|
||||
// @ts-expect-error
|
||||
"(" + this.typeReference.getParser().regexp.source + ")"
|
||||
+ "(?:" + this.quoted.getParser().parser.regexp.source + ")"
|
||||
// @ts-expect-error
|
||||
+ "(?:" + this.#quotedParser.getParser().parser.regexp.source + ")"
|
||||
)
|
||||
).map(([_full, type, ...path]) => new this({ type, path: path.find(v => v), _full }))
|
||||
static fullReferenceSerializedGrammar = Parsernostrum.regArray(
|
||||
).map(([full, type, ...path]) => new this(type, path.find(v => v), full))
|
||||
static fullReferenceSerializedGrammar = P.regArray(
|
||||
new RegExp(
|
||||
'"(' + Grammar.Regex.InsideString.source + "?)"
|
||||
+ "(?:'(" + Grammar.Regex.InsideSingleQuotedString.source + `?)')?"`
|
||||
)
|
||||
).map(([_full, type, path]) => new this({ type, path, _full }))
|
||||
static typeReferenceGrammar = this.typeReference.map(v => new this({ type: v, path: "", _full: v }))
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
constructor(values = {}) {
|
||||
if (values.constructor === String) {
|
||||
values = {
|
||||
path: values
|
||||
}
|
||||
}
|
||||
super(values)
|
||||
if (!values._full || values._full.length === 0) {
|
||||
this._full = `"${this.type + (this.path ? (`'${this.path}'`) : "")}"`
|
||||
}
|
||||
/** @type {String} */ this.type
|
||||
/** @type {String} */ this.path
|
||||
}
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.alt(
|
||||
).map(([full, type, path]) => new this(type, path, full))
|
||||
static typeReferenceGrammar = this.typeReference.map(v => new this(v, "", v))
|
||||
static grammar = /** @type {P<ObjectReferenceEntity>} */(
|
||||
P.alt(
|
||||
this.fullReferenceSerializedGrammar,
|
||||
this.fullReferenceGrammar,
|
||||
this.typeReferenceGrammar,
|
||||
)
|
||||
).label("ObjectReferenceEntity")
|
||||
)
|
||||
|
||||
#type
|
||||
get type() {
|
||||
return this.#type
|
||||
}
|
||||
set type(value) {
|
||||
this.#type = value
|
||||
}
|
||||
|
||||
#path
|
||||
get path() {
|
||||
return this.#path
|
||||
}
|
||||
set path(value) {
|
||||
this.#path = value
|
||||
}
|
||||
|
||||
#fullEscaped
|
||||
/** @type {String} */
|
||||
#full
|
||||
get full() {
|
||||
return this.#full
|
||||
}
|
||||
set full(value) {
|
||||
this.#full = value
|
||||
}
|
||||
|
||||
|
||||
constructor(type = "None", path = "", full = null) {
|
||||
super()
|
||||
this.#type = type
|
||||
this.#path = path
|
||||
this.#full = full ?? `"${this.type + (this.path ? (`'${this.path}'`) : "")}"`
|
||||
}
|
||||
|
||||
static createNoneInstance() {
|
||||
return new ObjectReferenceEntity({ type: "None", path: "" })
|
||||
return new ObjectReferenceEntity("None")
|
||||
}
|
||||
|
||||
getName(dropCounter = false) {
|
||||
return Utility.getNameFromPath(this.path.replace(/_C$/, ""), dropCounter)
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this._full
|
||||
/** @param {IEntity} other */
|
||||
equals(other) {
|
||||
if (!(other instanceof ObjectReferenceEntity)) {
|
||||
return false
|
||||
}
|
||||
return this.type == other.type && this.path == other.path
|
||||
}
|
||||
|
||||
toString(
|
||||
insideString = false,
|
||||
indentation = "",
|
||||
Self = this.Self(),
|
||||
printKey = Self.printKey,
|
||||
wrap = Self.wrap,
|
||||
) {
|
||||
if (insideString) {
|
||||
if (this.#fullEscaped === undefined) {
|
||||
this.#fullEscaped = Utility.escapeString(this.#full, false)
|
||||
}
|
||||
return this.#fullEscaped
|
||||
}
|
||||
return this.full
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
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: new AttributeInfo({
|
||||
default: "",
|
||||
}),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.symbol.map(v => new this(v))
|
||||
}
|
||||
|
||||
constructor(values) {
|
||||
if (values.constructor !== Object) {
|
||||
values = {
|
||||
value: values,
|
||||
}
|
||||
}
|
||||
super(values)
|
||||
/** @type {String} */ this.value
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.value
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.value
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
import P from "parsernostrum"
|
||||
import Configuration from "../Configuration.js"
|
||||
import pinColor from "../decoding/pinColor.js"
|
||||
import pinTitle from "../decoding/pinTitle.js"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import AlternativesEntity from "./AlternativesEntity.js"
|
||||
import ArrayEntity from "./ArrayEntity.js"
|
||||
import BooleanEntity from "./BooleanEntity.js"
|
||||
import ByteEntity from "./ByteEntity.js"
|
||||
import ComputedType from "./ComputedType.js"
|
||||
import ComputedTypeEntity from "./ComputedTypeEntity.js"
|
||||
import EnumDisplayValueEntity from "./EnumDisplayValueEntity.js"
|
||||
import EnumEntity from "./EnumEntity.js"
|
||||
import FormatTextEntity from "./FormatTextEntity.js"
|
||||
@@ -15,6 +18,7 @@ import IntegerEntity from "./IntegerEntity.js"
|
||||
import InvariantTextEntity from "./InvariantTextEntity.js"
|
||||
import LinearColorEntity from "./LinearColorEntity.js"
|
||||
import LocalizedTextEntity from "./LocalizedTextEntity.js"
|
||||
import NumberEntity from "./NumberEntity.js"
|
||||
import ObjectReferenceEntity from "./ObjectReferenceEntity.js"
|
||||
import PinReferenceEntity from "./PinReferenceEntity.js"
|
||||
import PinTypeEntity from "./PinTypeEntity.js"
|
||||
@@ -24,29 +28,30 @@ import SimpleSerializationRotatorEntity from "./SimpleSerializationRotatorEntity
|
||||
import SimpleSerializationVector2DEntity from "./SimpleSerializationVector2DEntity.js"
|
||||
import SimpleSerializationVector4DEntity from "./SimpleSerializationVector4DEntity.js"
|
||||
import SimpleSerializationVectorEntity from "./SimpleSerializationVectorEntity.js"
|
||||
import Union from "./Union.js"
|
||||
import StringEntity from "./StringEntity.js"
|
||||
import Vector2DEntity from "./Vector2DEntity.js"
|
||||
import Vector4DEntity from "./Vector4DEntity.js"
|
||||
import VectorEntity from "./VectorEntity.js"
|
||||
|
||||
/** @template {TerminalAttribute} T */
|
||||
/** @template {IEntity} T */
|
||||
export default class PinEntity extends IEntity {
|
||||
|
||||
static lookbehind = "Pin"
|
||||
static #typeEntityMap = {
|
||||
[Configuration.paths.linearColor]: LinearColorEntity,
|
||||
[Configuration.paths.rotator]: RotatorEntity,
|
||||
[Configuration.paths.vector]: VectorEntity,
|
||||
[Configuration.paths.vector2D]: Vector2DEntity,
|
||||
[Configuration.paths.vector4f]: Vector4DEntity,
|
||||
"bool": Boolean,
|
||||
"bool": BooleanEntity,
|
||||
"byte": ByteEntity,
|
||||
"enum": EnumEntity,
|
||||
"exec": String,
|
||||
"exec": StringEntity,
|
||||
"int": IntegerEntity,
|
||||
"int64": Integer64Entity,
|
||||
"name": String,
|
||||
"real": Number,
|
||||
"string": String,
|
||||
"name": StringEntity,
|
||||
"real": NumberEntity,
|
||||
"string": StringEntity,
|
||||
}
|
||||
static #alternativeTypeEntityMap = {
|
||||
"enum": EnumDisplayValueEntity,
|
||||
@@ -58,52 +63,38 @@ export default class PinEntity extends IEntity {
|
||||
[Configuration.paths.vector4f]: SimpleSerializationVector4DEntity,
|
||||
}
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
lookbehind: new AttributeInfo({
|
||||
default: "Pin",
|
||||
ignored: true,
|
||||
}),
|
||||
objectEntity: new AttributeInfo({
|
||||
ignored: true,
|
||||
}),
|
||||
pinIndex: new AttributeInfo({
|
||||
type: Number,
|
||||
ignored: true,
|
||||
}),
|
||||
PinId: new AttributeInfo({
|
||||
type: GuidEntity,
|
||||
default: () => new GuidEntity()
|
||||
}),
|
||||
PinName: AttributeInfo.createValue(""),
|
||||
PinFriendlyName: AttributeInfo.createType(new Union(LocalizedTextEntity, FormatTextEntity, InvariantTextEntity, String)),
|
||||
PinToolTip: AttributeInfo.createType(String),
|
||||
Direction: AttributeInfo.createType(String),
|
||||
PinType: new AttributeInfo({
|
||||
type: PinTypeEntity,
|
||||
default: () => new PinTypeEntity(),
|
||||
inlined: true,
|
||||
}),
|
||||
LinkedTo: AttributeInfo.createType([PinReferenceEntity]),
|
||||
SubPins: AttributeInfo.createType([PinReferenceEntity]),
|
||||
ParentPin: AttributeInfo.createType(PinReferenceEntity),
|
||||
DefaultValue: new AttributeInfo({
|
||||
type: new ComputedType(
|
||||
PinId: GuidEntity.withDefault(),
|
||||
PinName: StringEntity.withDefault(),
|
||||
PinFriendlyName: AlternativesEntity.accepting(
|
||||
LocalizedTextEntity,
|
||||
FormatTextEntity,
|
||||
InvariantTextEntity,
|
||||
StringEntity
|
||||
),
|
||||
PinToolTip: StringEntity,
|
||||
Direction: StringEntity,
|
||||
PinType: PinTypeEntity.withDefault().flagInlined(),
|
||||
LinkedTo: ArrayEntity.of(PinReferenceEntity).withDefault().flagSilent(),
|
||||
SubPins: ArrayEntity.of(PinReferenceEntity),
|
||||
ParentPin: PinReferenceEntity,
|
||||
DefaultValue:
|
||||
ComputedTypeEntity.from(
|
||||
/** @param {PinEntity} pinEntity */
|
||||
pinEntity => pinEntity.getEntityType(true) ?? String
|
||||
),
|
||||
serialized: true,
|
||||
}),
|
||||
AutogeneratedDefaultValue: AttributeInfo.createType(String),
|
||||
DefaultObject: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
PersistentGuid: AttributeInfo.createType(GuidEntity),
|
||||
bHidden: AttributeInfo.createValue(false),
|
||||
bNotConnectable: AttributeInfo.createValue(false),
|
||||
bDefaultValueIsReadOnly: AttributeInfo.createValue(false),
|
||||
bDefaultValueIsIgnored: AttributeInfo.createValue(false),
|
||||
bAdvancedView: AttributeInfo.createValue(false),
|
||||
bOrphanedPin: AttributeInfo.createValue(false),
|
||||
pinEntity => pinEntity.getEntityType(true) ?? StringEntity
|
||||
).flagSerialized(),
|
||||
AutogeneratedDefaultValue: StringEntity,
|
||||
DefaultObject: ObjectReferenceEntity,
|
||||
PersistentGuid: GuidEntity,
|
||||
bHidden: BooleanEntity.withDefault(),
|
||||
bNotConnectable: BooleanEntity.withDefault(),
|
||||
bDefaultValueIsReadOnly: BooleanEntity.withDefault(),
|
||||
bDefaultValueIsIgnored: BooleanEntity.withDefault(),
|
||||
bAdvancedView: BooleanEntity.withDefault(),
|
||||
bOrphanedPin: BooleanEntity.withDefault(),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
static grammar = /** @type {P<PinEntity>} */(
|
||||
Grammar.createEntityGrammar(this)
|
||||
)
|
||||
|
||||
#recomputesNodeTitleOnChange = false
|
||||
set recomputesNodeTitleOnChange(value) {
|
||||
@@ -113,42 +104,52 @@ export default class PinEntity extends IEntity {
|
||||
return this.#recomputesNodeTitleOnChange
|
||||
}
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.createEntityGrammar(this)
|
||||
#objectEntity
|
||||
get objectEntity() {
|
||||
return this.#objectEntity
|
||||
}
|
||||
set objectEntity(value) {
|
||||
this.#objectEntity = value
|
||||
}
|
||||
|
||||
constructor(values = {}, suppressWarns = false) {
|
||||
super(values, suppressWarns)
|
||||
/** @type {ObjectEntity} */ this.objectEntity
|
||||
/** @type {Number} */ this.pinIndex
|
||||
/** @type {GuidEntity} */ this.PinId
|
||||
/** @type {String} */ this.PinName
|
||||
/** @type {LocalizedTextEntity | String} */ this.PinFriendlyName
|
||||
/** @type {String} */ this.PinToolTip
|
||||
/** @type {String} */ this.Direction
|
||||
/** @type {PinTypeEntity} */ this.PinType
|
||||
/** @type {PinReferenceEntity[]} */ this.LinkedTo
|
||||
#pinIndex
|
||||
get pinIndex() {
|
||||
return this.#pinIndex
|
||||
}
|
||||
set pinIndex(value) {
|
||||
this.#pinIndex = value
|
||||
}
|
||||
|
||||
constructor(values = {}) {
|
||||
super(values)
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.PinId>} */ this.PinId
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.PinName>} */ this.PinName
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.PinFriendlyName>} */ this.PinFriendlyName
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.PinToolTip>} */ this.PinToolTip
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.Direction>} */ this.Direction
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.PinType>} */ this.PinType
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.LinkedTo>} */ this.LinkedTo
|
||||
/** @type {T} */ this.DefaultValue
|
||||
/** @type {String} */ this.AutogeneratedDefaultValue
|
||||
/** @type {ObjectReferenceEntity} */ this.DefaultObject
|
||||
/** @type {GuidEntity} */ this.PersistentGuid
|
||||
/** @type {Boolean} */ this.bHidden
|
||||
/** @type {Boolean} */ this.bNotConnectable
|
||||
/** @type {Boolean} */ this.bDefaultValueIsReadOnly
|
||||
/** @type {Boolean} */ this.bDefaultValueIsIgnored
|
||||
/** @type {Boolean} */ this.bAdvancedView
|
||||
/** @type {Boolean} */ this.bOrphanedPin
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.AutogeneratedDefaultValue>} */ this.AutogeneratedDefaultValue
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.DefaultObject>} */ this.DefaultObject
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.PersistentGuid>} */ this.PersistentGuid
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.bHidden>} */ this.bHidden
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.bNotConnectable>} */ this.bNotConnectable
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.bDefaultValueIsReadOnly>} */ this.bDefaultValueIsReadOnly
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.bDefaultValueIsIgnored>} */ this.bDefaultValueIsIgnored
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.bAdvancedView>} */ this.bAdvancedView
|
||||
/** @type {InstanceType<typeof PinEntity.attributes.bOrphanedPin>} */ this.bOrphanedPin
|
||||
}
|
||||
|
||||
/** @param {ObjectEntity} objectEntity */
|
||||
static fromLegacyObject(objectEntity) {
|
||||
return new PinEntity(objectEntity, true)
|
||||
return new PinEntity(objectEntity)
|
||||
}
|
||||
|
||||
getType() {
|
||||
const category = this.PinType.PinCategory.toLocaleLowerCase()
|
||||
const category = this.PinType.PinCategory?.valueOf().toLocaleLowerCase()
|
||||
if (category === "struct" || category === "class" || category === "object" || category === "type") {
|
||||
return this.PinType.PinSubCategoryObject.path
|
||||
return this.PinType.PinSubCategoryObject?.path
|
||||
}
|
||||
if (this.isEnum()) {
|
||||
return "enum"
|
||||
@@ -161,7 +162,7 @@ export default class PinEntity extends IEntity {
|
||||
if (pinObjectReference) {
|
||||
/** @type {ObjectEntity} */
|
||||
const pinObject = pcgSuboject[Configuration.subObjectAttributeNameFromReference(pinObjectReference, true)]
|
||||
let allowedTypes = pinObject.Properties?.AllowedTypes?.toString() ?? ""
|
||||
let allowedTypes = pinObject.Properties?.AllowedTypes?.valueOf() ?? ""
|
||||
if (allowedTypes == "") {
|
||||
allowedTypes = this.PinType.PinCategory ?? ""
|
||||
if (allowedTypes == "") {
|
||||
@@ -170,8 +171,8 @@ export default class PinEntity extends IEntity {
|
||||
}
|
||||
if (allowedTypes) {
|
||||
if (
|
||||
pinObject.Properties.bAllowMultipleData !== false
|
||||
&& pinObject.Properties.bAllowMultipleConnections !== false
|
||||
pinObject.Properties.bAllowMultipleData?.valueOf() !== false
|
||||
&& pinObject.Properties.bAllowMultipleConnections?.valueOf() !== false
|
||||
) {
|
||||
allowedTypes += "[]"
|
||||
}
|
||||
@@ -180,7 +181,8 @@ export default class PinEntity extends IEntity {
|
||||
}
|
||||
}
|
||||
if (category === "optional") {
|
||||
switch (this.PinType.PinSubCategory) {
|
||||
const subCategory = this.PinType.PinSubCategory?.valueOf()
|
||||
switch (subCategory) {
|
||||
case "red":
|
||||
return "real"
|
||||
case "rg":
|
||||
@@ -190,12 +192,13 @@ export default class PinEntity extends IEntity {
|
||||
case "rgba":
|
||||
return Configuration.paths.linearColor
|
||||
default:
|
||||
return this.PinType.PinSubCategory
|
||||
return subCategory
|
||||
}
|
||||
}
|
||||
return category
|
||||
}
|
||||
|
||||
/** @returns {typeof IEntity} */
|
||||
getEntityType(alternative = false) {
|
||||
const typeString = this.getType()
|
||||
const entity = PinEntity.#typeEntityMap[typeString]
|
||||
@@ -211,22 +214,11 @@ 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.bSerializeAsSinglePrecisionFloat = other.PinType.bSerializeAsSinglePrecisionFloat
|
||||
this.PinType = other.PinType
|
||||
}
|
||||
|
||||
getDefaultValue(maybeCreate = false) {
|
||||
if (this.DefaultValue === undefined && maybeCreate) {
|
||||
// @ts-expect-error
|
||||
this.DefaultValue = new (this.getEntityType(true))()
|
||||
}
|
||||
return this.DefaultValue
|
||||
@@ -240,19 +232,19 @@ export default class PinEntity extends IEntity {
|
||||
}
|
||||
|
||||
isExecution() {
|
||||
return this.PinType.PinCategory === "exec"
|
||||
return this.PinType.PinCategory.toString() === "exec"
|
||||
}
|
||||
|
||||
isHidden() {
|
||||
return this.bHidden
|
||||
return this.bHidden?.valueOf()
|
||||
}
|
||||
|
||||
isInput() {
|
||||
return !this.bHidden && this.Direction != "EGPD_Output"
|
||||
return !this.isHidden() && this.Direction.valueOf() != "EGPD_Output"
|
||||
}
|
||||
|
||||
isOutput() {
|
||||
return !this.bHidden && this.Direction == "EGPD_Output"
|
||||
return !this.isHidden() && this.Direction.valueOf() == "EGPD_Output"
|
||||
}
|
||||
|
||||
isLinked() {
|
||||
@@ -265,15 +257,12 @@ export default class PinEntity extends IEntity {
|
||||
* @returns true if it was not already linked to the tarket
|
||||
*/
|
||||
linkTo(targetObjectName, targetPinEntity) {
|
||||
const linkFound = this.LinkedTo?.some(pinReferenceEntity =>
|
||||
const linkFound = this.LinkedTo.values?.some(pinReferenceEntity =>
|
||||
pinReferenceEntity.objectName.toString() == targetObjectName
|
||||
&& pinReferenceEntity.pinGuid.valueOf() == targetPinEntity.PinId.valueOf()
|
||||
)
|
||||
if (!linkFound) {
|
||||
(this.LinkedTo ??= []).push(new PinReferenceEntity({
|
||||
objectName: targetObjectName,
|
||||
pinGuid: targetPinEntity.PinId,
|
||||
}))
|
||||
this.LinkedTo.values.push(new PinReferenceEntity(targetObjectName, targetPinEntity.PinId,))
|
||||
return true
|
||||
}
|
||||
return false // Already linked
|
||||
@@ -285,12 +274,12 @@ export default class PinEntity extends IEntity {
|
||||
* @returns true if it was linked to the target
|
||||
*/
|
||||
unlinkFrom(targetObjectName, targetPinEntity) {
|
||||
const indexElement = this.LinkedTo?.findIndex(pinReferenceEntity => {
|
||||
const indexElement = this.LinkedTo.values?.findIndex(pinReferenceEntity => {
|
||||
return pinReferenceEntity.objectName.toString() == targetObjectName
|
||||
&& pinReferenceEntity.pinGuid.valueOf() == targetPinEntity.PinId.valueOf()
|
||||
})
|
||||
if (indexElement >= 0) {
|
||||
this.LinkedTo.splice(indexElement, 1)
|
||||
this.LinkedTo.values.splice(indexElement, 1)
|
||||
if (this.LinkedTo.length === 0 && PinEntity.attributes.LinkedTo.default === undefined) {
|
||||
this.LinkedTo = undefined
|
||||
}
|
||||
|
||||
@@ -1,34 +1,31 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P from "parsernostrum"
|
||||
import GuidEntity from "./GuidEntity.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
import PathSymbolEntity from "./PathSymbolEntity.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import SymbolEntity from "./SymbolEntity.js"
|
||||
|
||||
export default class PinReferenceEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
objectName: AttributeInfo.createType(PathSymbolEntity),
|
||||
pinGuid: AttributeInfo.createType(GuidEntity),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.seq(
|
||||
PathSymbolEntity.grammar,
|
||||
Parsernostrum.whitespace,
|
||||
static grammar = /** @type {P<PinReferenceEntity>} */(
|
||||
P.seq(
|
||||
SymbolEntity.grammar,
|
||||
P.whitespace,
|
||||
GuidEntity.grammar
|
||||
).map(
|
||||
([objectName, _1, pinGuid]) => new this({
|
||||
objectName: objectName,
|
||||
pinGuid: pinGuid,
|
||||
})
|
||||
)
|
||||
.map(([objectName, _1, pinGuid]) => new this(objectName, pinGuid))
|
||||
.label("PinReferenceEntity")
|
||||
)
|
||||
|
||||
/**
|
||||
* @param {SymbolEntity} objectName
|
||||
* @param {GuidEntity} pinGuid
|
||||
*/
|
||||
constructor(objectName = null, pinGuid = null) {
|
||||
super()
|
||||
this.objectName = objectName
|
||||
this.pinGuid = pinGuid
|
||||
}
|
||||
|
||||
constructor(values) {
|
||||
super(values)
|
||||
/** @type {PathSymbolEntity} */ this.objectName
|
||||
/** @type {GuidEntity} */ this.pinGuid
|
||||
toString() {
|
||||
return this.objectName.toString() + " " + this.pinGuid.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,69 +1,52 @@
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import BooleanEntity from "./BooleanEntity.js"
|
||||
import FunctionReferenceEntity from "./FunctionReferenceEntity.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
import ObjectReferenceEntity from "./ObjectReferenceEntity.js"
|
||||
import PathSymbolEntity from "./PathSymbolEntity.js"
|
||||
import StringEntity from "./StringEntity.js"
|
||||
import SymbolEntity from "./SymbolEntity.js"
|
||||
|
||||
export default class PinTypeEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
PinCategory: AttributeInfo.createValue(""),
|
||||
PinSubCategory: AttributeInfo.createValue(""),
|
||||
PinSubCategoryObject: new AttributeInfo({
|
||||
type: ObjectReferenceEntity,
|
||||
default: () => ObjectReferenceEntity.createNoneInstance(),
|
||||
}),
|
||||
PinSubCategoryMemberReference: new AttributeInfo({
|
||||
type: FunctionReferenceEntity,
|
||||
default: null,
|
||||
}),
|
||||
PinValueType: new AttributeInfo({
|
||||
type: PinTypeEntity,
|
||||
default: null,
|
||||
}),
|
||||
ContainerType: AttributeInfo.createType(PathSymbolEntity),
|
||||
bIsReference: AttributeInfo.createValue(false),
|
||||
bIsConst: AttributeInfo.createValue(false),
|
||||
bIsWeakPointer: AttributeInfo.createValue(false),
|
||||
bIsUObjectWrapper: AttributeInfo.createValue(false),
|
||||
bSerializeAsSinglePrecisionFloat: AttributeInfo.createValue(false),
|
||||
PinCategory: StringEntity.withDefault(),
|
||||
PinSubCategory: StringEntity.withDefault(),
|
||||
PinSubCategoryObject: ObjectReferenceEntity.withDefault(),
|
||||
PinSubCategoryMemberReference: FunctionReferenceEntity.withDefault(),
|
||||
ContainerType: SymbolEntity,
|
||||
bIsReference: BooleanEntity.withDefault(),
|
||||
bIsConst: BooleanEntity.withDefault(),
|
||||
bIsWeakPointer: BooleanEntity.withDefault(),
|
||||
bIsUObjectWrapper: BooleanEntity.withDefault(),
|
||||
bSerializeAsSinglePrecisionFloat: BooleanEntity.withDefault(),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
static grammar = /** @type {P<PinTypeEntity>} */(
|
||||
Grammar.createEntityGrammar(this).label("PinTypeEntity")
|
||||
)
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.createEntityGrammar(this)
|
||||
}
|
||||
|
||||
constructor(values = {}, suppressWarns = false) {
|
||||
super(values, suppressWarns)
|
||||
/** @type {String} */ this.PinCategory
|
||||
/** @type {String} */ this.PinSubCategory
|
||||
/** @type {ObjectReferenceEntity} */ this.PinSubCategoryObject
|
||||
/** @type {FunctionReferenceEntity} */ this.PinSubCategoryMemberReference
|
||||
/** @type {PinTypeEntity} */ this.PinValueType
|
||||
/** @type {PathSymbolEntity} */ this.ContainerType
|
||||
/** @type {Boolean} */ this.bIsReference
|
||||
/** @type {Boolean} */ this.bIsConst
|
||||
/** @type {Boolean} */ this.bIsWeakPointer
|
||||
/** @type {Boolean} */ this.bIsUObjectWrapper
|
||||
/** @type {Boolean} */ this.bIsUObjectWrapper
|
||||
/** @type {Boolean} */ this.bSerializeAsSinglePrecisionFloat
|
||||
constructor(values = {}) {
|
||||
super(values)
|
||||
/** @type {InstanceType<typeof PinTypeEntity.attributes.PinCategory>} */ this.PinCategory
|
||||
/** @type {InstanceType<typeof PinTypeEntity.attributes.PinSubCategory>} */ this.PinSubCategory
|
||||
/** @type {InstanceType<typeof PinTypeEntity.attributes.PinSubCategoryObject>} */ this.PinSubCategoryObject
|
||||
/** @type {InstanceType<typeof PinTypeEntity.attributes.PinSubCategoryMemberReference>} */ this.PinSubCategoryMemberReference
|
||||
/** @type {InstanceType<typeof PinTypeEntity.attributes.ContainerType>} */ this.ContainerType
|
||||
/** @type {InstanceType<typeof PinTypeEntity.attributes.bIsReference>} */ this.bIsReference
|
||||
/** @type {InstanceType<typeof PinTypeEntity.attributes.bIsConst>} */ this.bIsConst
|
||||
/** @type {InstanceType<typeof PinTypeEntity.attributes.bIsWeakPointer>} */ this.bIsWeakPointer
|
||||
/** @type {InstanceType<typeof PinTypeEntity.attributes.bIsUObjectWrapper>} */ this.bIsUObjectWrapper
|
||||
/** @type {InstanceType<typeof PinTypeEntity.attributes.bIsUObjectWrapper>} */ this.bIsUObjectWrapper
|
||||
/** @type {InstanceType<typeof PinTypeEntity.attributes.bSerializeAsSinglePrecisionFloat>} */ this.bSerializeAsSinglePrecisionFloat
|
||||
}
|
||||
|
||||
/** @param {PinTypeEntity} other */
|
||||
copyTypeFrom(other) {
|
||||
this.PinCategory = other.PinCategory
|
||||
this.PinSubCategory = other.PinSubCategory
|
||||
this.PinSubCategoryObject = other.PinSubCategoryObject
|
||||
this.PinSubCategoryMemberReference = other.PinSubCategoryMemberReference
|
||||
this.PinValueType = other.PinValueType
|
||||
this.ContainerType = other.ContainerType
|
||||
this.bIsReference = other.bIsReference
|
||||
this.bIsConst = other.bIsConst
|
||||
this.bIsWeakPointer = other.bIsWeakPointer
|
||||
this.bIsUObjectWrapper = other.bIsUObjectWrapper
|
||||
this.bSerializeAsSinglePrecisionFloat = other.bSerializeAsSinglePrecisionFloat
|
||||
for (const key of this.keys) {
|
||||
if (other[key] !== undefined) {
|
||||
this[key] = other[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import Vector2DEntity from "./Vector2DEntity.js"
|
||||
|
||||
export default class RBSerializationVector2DEntity extends Vector2DEntity {
|
||||
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.alt(
|
||||
Parsernostrum.regArray(new RegExp(
|
||||
/X\s*=\s*/.source + "(?<x>" + Parsernostrum.number.getParser().parser.regexp.source + ")"
|
||||
+ "\\s+"
|
||||
+ /Y\s*=\s*/.source + "(?<y>" + Parsernostrum.number.getParser().parser.regexp.source + ")"
|
||||
)).map(({ groups: { x, y } }) => new this({
|
||||
X: Number(x),
|
||||
Y: Number(y),
|
||||
})),
|
||||
Vector2DEntity.grammar
|
||||
)
|
||||
}
|
||||
static grammar = /** @type {P<RBSerializationVector2DEntity>} */(P.alt(
|
||||
P.regArray(new RegExp(
|
||||
/X\s*=\s*/.source + "(?<x>" + Grammar.numberRegexSource + ")"
|
||||
+ "\\s+"
|
||||
+ /Y\s*=\s*/.source + "(?<y>" + Grammar.numberRegexSource + ")"
|
||||
)).map(({ groups: { x, y } }) => new this({
|
||||
X: Number(x),
|
||||
Y: Number(y),
|
||||
})),
|
||||
Vector2DEntity.grammar
|
||||
).label("RBSerializationVector2DEntity"))
|
||||
}
|
||||
|
||||
@@ -1,35 +1,25 @@
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
import NumberEntity from "./NumberEntity.js"
|
||||
|
||||
export default class RotatorEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
R: new AttributeInfo({
|
||||
default: 0,
|
||||
expected: true,
|
||||
}),
|
||||
P: new AttributeInfo({
|
||||
default: 0,
|
||||
expected: true,
|
||||
}),
|
||||
Y: new AttributeInfo({
|
||||
default: 0,
|
||||
expected: true,
|
||||
}),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.createEntityGrammar(this, false)
|
||||
R: NumberEntity.withDefault(),
|
||||
P: NumberEntity.withDefault(),
|
||||
Y: NumberEntity.withDefault(),
|
||||
}
|
||||
static grammar = /** @type {P<RotatorEntity>} */(
|
||||
Grammar.createEntityGrammar(this, Grammar.commaSeparation, true).label("RotatorEntity")
|
||||
)
|
||||
|
||||
constructor(values) {
|
||||
super(values)
|
||||
/** @type {Number} */ this.R
|
||||
/** @type {Number} */ this.P
|
||||
/** @type {Number} */ this.Y
|
||||
/** @type {InstanceType<typeof RotatorEntity.attributes.R>} */ this.R
|
||||
/** @type {InstanceType<typeof RotatorEntity.attributes.P>} */ this.P
|
||||
/** @type {InstanceType<typeof RotatorEntity.attributes.Y>} */ this.Y
|
||||
}
|
||||
|
||||
getRoll() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import P from "parsernostrum"
|
||||
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"
|
||||
@@ -8,18 +8,16 @@ export default class ScriptVariableEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
ScriptVariable: AttributeInfo.createType(ObjectReferenceEntity),
|
||||
OriginalChangeId: AttributeInfo.createType(GuidEntity),
|
||||
ScriptVariable: ObjectReferenceEntity,
|
||||
OriginalChangeId: GuidEntity,
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
static grammar = /** @type {P<ScriptVariableEntity>} */(
|
||||
Grammar.createEntityGrammar(this).label("ScriptVariableEntity")
|
||||
)
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.createEntityGrammar(this)
|
||||
}
|
||||
|
||||
constructor(values = {}, suppressWarns = false) {
|
||||
super(values, suppressWarns)
|
||||
/** @type {ObjectReferenceEntity} */ this.ScriptVariable
|
||||
/** @type {GuidEntity} */ this.OriginalChangeId
|
||||
constructor(values = {}) {
|
||||
super(values)
|
||||
/** @type {InstanceType<typeof ScriptVariableEntity.attributes.ScriptVariable>} */ this.ScriptVariable
|
||||
/** @type {InstanceType<typeof ScriptVariableEntity.attributes.OriginalChangeId>} */ this.OriginalChangeId
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,41 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import RotatorEntity from "./RotatorEntity.js"
|
||||
import NumberEntity from "./NumberEntity.js"
|
||||
|
||||
export default class SimpleSerializationRotatorEntity extends RotatorEntity {
|
||||
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
const number = Parsernostrum.number.getParser().parser.regexp.source
|
||||
return Parsernostrum.alt(
|
||||
Parsernostrum.regArray(new RegExp(
|
||||
"(" + number + ")"
|
||||
+ "\\s*,\\s*"
|
||||
+ "(" + number + ")"
|
||||
+ "\\s*,\\s*"
|
||||
+ "(" + number + ")"
|
||||
)).map(([_, p, y, r]) => new this({
|
||||
R: Number(r),
|
||||
P: Number(p),
|
||||
Y: Number(y),
|
||||
static attributeSeparator = ", "
|
||||
static grammar = /** @type {P<SimpleSerializationRotatorEntity>} */(
|
||||
P.alt(
|
||||
P.regArray(new RegExp(
|
||||
`(${NumberEntity.numberRegexSource})`
|
||||
+ String.raw`\s*,\s*`
|
||||
+ `(${NumberEntity.numberRegexSource})`
|
||||
+ String.raw`\s*,\s*`
|
||||
+ `(${NumberEntity.numberRegexSource})`
|
||||
)).map(([_, p, pPrecision, y, yPrecision, r, rPrecision]) => new this({
|
||||
R: new NumberEntity(r, rPrecision?.length),
|
||||
P: new NumberEntity(p, pPrecision?.length),
|
||||
Y: new NumberEntity(y, yPrecision?.length),
|
||||
})),
|
||||
RotatorEntity.grammar
|
||||
)
|
||||
RotatorEntity.grammar.map(v => new this({
|
||||
R: v.R,
|
||||
P: v.P,
|
||||
Y: v.Y,
|
||||
}))
|
||||
).label("SimpleSerializationRotatorEntity")
|
||||
)
|
||||
|
||||
toString(
|
||||
insideString = false,
|
||||
indentation = "",
|
||||
Self = this.Self(),
|
||||
printKey = Self.printKey,
|
||||
wrap = Self.wrap,
|
||||
) {
|
||||
return this.P.toString() + Self.attributeSeparator
|
||||
+ this.Y.toString() + Self.attributeSeparator
|
||||
+ this.R.toString() + (this.trailing ? Self.attributeSeparator : "")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,36 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import Vector2DEntity from "./Vector2DEntity.js"
|
||||
import NumberEntity from "./NumberEntity.js"
|
||||
|
||||
export default class SimpleSerializationVector2DEntity extends Vector2DEntity {
|
||||
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
const number = Parsernostrum.number.getParser().parser.regexp.source
|
||||
return Parsernostrum.alt(
|
||||
Parsernostrum.regArray(new RegExp(
|
||||
"(" + number + ")"
|
||||
+ "\\s*,\\s*"
|
||||
+ "(" + number + ")"
|
||||
)).map(([_, x, y]) => new this({
|
||||
X: Number(x),
|
||||
Y: Number(y),
|
||||
static attributeSeparator = ", "
|
||||
static grammar = /** @type {P<SimpleSerializationVector2DEntity>} */(
|
||||
P.alt(
|
||||
P.regArray(new RegExp(
|
||||
`(${NumberEntity.numberRegexSource})`
|
||||
+ String.raw`\s*,\s*`
|
||||
+ `(${NumberEntity.numberRegexSource})`
|
||||
)).map(([_, x, xPrecision, y, yPrecision]) => new this({
|
||||
X: new NumberEntity(x, xPrecision?.length),
|
||||
Y: new NumberEntity(y, yPrecision?.length),
|
||||
})),
|
||||
Vector2DEntity.grammar
|
||||
)
|
||||
Vector2DEntity.grammar.map(v => new this({
|
||||
X: v.X,
|
||||
Y: v.Y,
|
||||
}))
|
||||
).label("SimpleSerializationVector2DEntity")
|
||||
)
|
||||
|
||||
toString(
|
||||
insideString = false,
|
||||
indentation = "",
|
||||
Self = this.Self(),
|
||||
printKey = Self.printKey,
|
||||
wrap = Self.wrap,
|
||||
) {
|
||||
return this.X.toString() + Self.attributeSeparator
|
||||
+ this.Y.toString() + (this.trailing ? Self.attributeSeparator : "")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import Vector4DEntity from "./Vector4DEntity.js"
|
||||
|
||||
export default class SimpleSerializationVector4DEntity extends Vector4DEntity {
|
||||
|
||||
static grammar = this.createGrammar()
|
||||
static grammar = /** @type {P<SimpleSerializationVector4DEntity> } */(this.createGrammar())
|
||||
|
||||
static createGrammar() {
|
||||
const number = Parsernostrum.number.getParser().parser.regexp.source
|
||||
return Parsernostrum.alt(
|
||||
Parsernostrum.regArray(new RegExp(
|
||||
"(" + number + ")"
|
||||
+ "\\s*,\\s*"
|
||||
+ "(" + number + ")"
|
||||
+ "\\s*,\\s*"
|
||||
+ "(" + number + ")"
|
||||
+ "\\s*,\\s*"
|
||||
+ "(" + number + ")"
|
||||
const number = Grammar.numberRegexSource
|
||||
return P.alt(
|
||||
P.regArray(new RegExp(
|
||||
`(${Grammar.numberRegexSource})`
|
||||
+ String.raw`\s*,\s*`
|
||||
+ `(${Grammar.numberRegexSource})`
|
||||
+ String.raw`\s*,\s*`
|
||||
+ `(${Grammar.numberRegexSource})`
|
||||
+ String.raw`\s*,\s*`
|
||||
+ `(${Grammar.numberRegexSource})`
|
||||
))
|
||||
.map(([_0, x, y, z, w]) => new this({
|
||||
X: Number(x),
|
||||
|
||||
@@ -1,26 +1,42 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import VectorEntity from "./VectorEntity.js"
|
||||
import NumberEntity from "./NumberEntity.js"
|
||||
|
||||
export default class SimpleSerializationVectorEntity extends VectorEntity {
|
||||
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
const number = Parsernostrum.number.getParser().parser.regexp.source
|
||||
return Parsernostrum.alt(
|
||||
Parsernostrum.regArray(new RegExp(
|
||||
"(" + number + ")"
|
||||
+ "\\s*,\\s*"
|
||||
+ "(" + number + ")"
|
||||
+ "\\s*,\\s*"
|
||||
+ "(" + number + ")"
|
||||
static attributeSeparator = ", "
|
||||
static grammar = /** @type {P<SimpleSerializationVectorEntity>} */(
|
||||
P.alt(
|
||||
P.regArray(new RegExp(
|
||||
`(${NumberEntity.numberRegexSource})`
|
||||
+ String.raw`\s*,\s*`
|
||||
+ `(${NumberEntity.numberRegexSource})`
|
||||
+ String.raw`\s*,\s*`
|
||||
+ `(${NumberEntity.numberRegexSource})`
|
||||
))
|
||||
.map(([_0, x, y, z]) => new this({
|
||||
X: Number(x),
|
||||
Y: Number(y),
|
||||
Z: Number(z),
|
||||
.map(([_, x, xPrecision, y, yPrecision, z, zPrecision]) => new this({
|
||||
X: new NumberEntity(x, xPrecision?.length),
|
||||
Y: new NumberEntity(y, yPrecision?.length),
|
||||
Z: new NumberEntity(z, zPrecision?.length),
|
||||
})),
|
||||
VectorEntity.grammar
|
||||
VectorEntity.grammar.map(v => new this({
|
||||
X: v.X,
|
||||
Y: v.Y,
|
||||
Z: v.Z,
|
||||
}))
|
||||
)
|
||||
)
|
||||
|
||||
toString(
|
||||
insideString = false,
|
||||
indentation = "",
|
||||
Self = this.Self(),
|
||||
printKey = Self.printKey,
|
||||
wrap = Self.wrap,
|
||||
) {
|
||||
return this.X.toString() + Self.attributeSeparator
|
||||
+ this.Y.toString() + Self.attributeSeparator
|
||||
+ this.Z.toString() + (this.trailing ? Self.attributeSeparator : "")
|
||||
}
|
||||
}
|
||||
|
||||
36
js/entity/StringEntity.js
Executable file
36
js/entity/StringEntity.js
Executable file
@@ -0,0 +1,36 @@
|
||||
import P from "parsernostrum"
|
||||
import Utility from "../Utility.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
|
||||
export default class StringEntity extends IEntity {
|
||||
|
||||
static grammar = /** @type {P<StringEntity>} */(
|
||||
P.doubleQuotedString
|
||||
.map(insideString => new this(Utility.unescapeString(insideString)))
|
||||
.label("StringEntity")
|
||||
)
|
||||
|
||||
/** @param {String} value */
|
||||
constructor(value = "") {
|
||||
super()
|
||||
this.value = value
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.value
|
||||
}
|
||||
|
||||
toString(
|
||||
insideString = false,
|
||||
indentation = "",
|
||||
Self = this.Self(),
|
||||
printKey = Self.printKey,
|
||||
wrap = Self.wrap,
|
||||
) {
|
||||
let result = `"${Utility.escapeString(this.value)}"`
|
||||
if (insideString) {
|
||||
result = Utility.escapeString(result, false)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,20 @@
|
||||
import P from "parsernostrum"
|
||||
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: AttributeInfo.createValue(""),
|
||||
static attributeConverter = {
|
||||
fromAttribute: (value, type) => new this(value),
|
||||
toAttribute: (value, type) => value.toString()
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
static grammar = /** @type {P<SymbolEntity>} */(
|
||||
Grammar.symbol.map(v => new this(v)).label("SymbolEntity")
|
||||
)
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.symbol.map(v => new this(v))
|
||||
}
|
||||
|
||||
/** @param {String | Object} values */
|
||||
constructor(values) {
|
||||
if (values.constructor !== Object) {
|
||||
values = {
|
||||
value: values,
|
||||
}
|
||||
}
|
||||
super(values)
|
||||
/** @type {String} */ this.value
|
||||
constructor(value = "") {
|
||||
super()
|
||||
this.value = value
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import BooleanEntity from "./BooleanEntity.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
import StringEntity from "./StringEntity.js"
|
||||
|
||||
export default class TerminalTypeEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
TerminalCategory: AttributeInfo.createType(String),
|
||||
TerminalSubCategory: AttributeInfo.createType(String),
|
||||
bTerminalIsConst: AttributeInfo.createType(Boolean),
|
||||
bTerminalIsWeakPointer: AttributeInfo.createType(Boolean),
|
||||
bTerminalIsUObjectWrapper: AttributeInfo.createType(Boolean),
|
||||
TerminalCategory: StringEntity,
|
||||
TerminalSubCategory: StringEntity,
|
||||
bTerminalIsConst: BooleanEntity,
|
||||
bTerminalIsWeakPointer: BooleanEntity,
|
||||
bTerminalIsUObjectWrapper: BooleanEntity,
|
||||
}
|
||||
static grammar = /** @type {P<TerminalTypeEntity>} */(
|
||||
Grammar.createEntityGrammar(this)
|
||||
)
|
||||
|
||||
constructor(values) {
|
||||
super(values)
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/** @template {any[]} T */
|
||||
export default class Union {
|
||||
|
||||
/** @type {T} */
|
||||
#values
|
||||
get values() {
|
||||
return this.#values
|
||||
}
|
||||
|
||||
/** @param {T} values */
|
||||
constructor(...values) {
|
||||
this.#values = values
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,21 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import P 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 grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.seq(
|
||||
static grammar = /** @type {P<UnknownKeysEntity>} */(
|
||||
P.seq(
|
||||
// Lookbehind
|
||||
Parsernostrum.reg(
|
||||
new RegExp(`(${Grammar.Regex.Path.source}|${Grammar.Regex.Symbol.source}\\s*)?\\(\\s*`),
|
||||
1
|
||||
),
|
||||
Parsernostrum.seq(Grammar.attributeName, Grammar.equalSeparation).map(([attribute, equal]) => attribute)
|
||||
P.reg(new RegExp(`(${Grammar.Regex.Path.source}|${Grammar.Regex.Symbol.source}\\s*)?\\(\\s*`), 1),
|
||||
P.seq(Grammar.attributeName, Grammar.equalSeparation).map(([attribute, equal]) => attribute)
|
||||
.chain(attributeName =>
|
||||
Grammar.unknownValue.map(attributeValue =>
|
||||
this.unknownEntityGrammar.map(attributeValue =>
|
||||
values => values[attributeName] = attributeValue
|
||||
)
|
||||
)
|
||||
.sepBy(Grammar.commaSeparation),
|
||||
Parsernostrum.reg(/\s*(?:,\s*)?\)/),
|
||||
P.reg(/\s*(?:,\s*)?\)/),
|
||||
).map(([lookbehind, attributes, _2]) => {
|
||||
lookbehind ??= ""
|
||||
let values = {}
|
||||
@@ -31,10 +24,10 @@ export default class UnknownKeysEntity extends IEntity {
|
||||
}
|
||||
attributes.forEach(attributeSetter => attributeSetter(values))
|
||||
return new this(values)
|
||||
})
|
||||
}
|
||||
}).label("UnknownKeysEntity")
|
||||
)
|
||||
|
||||
constructor(values) {
|
||||
super(values, true)
|
||||
static {
|
||||
IEntity.unknownEntity = this
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import PinEntity from "./PinEntity.js"
|
||||
|
||||
export default class UnknownPinEntity extends PinEntity {
|
||||
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Parsernostrum.seq(
|
||||
Parsernostrum.reg(
|
||||
new RegExp(`(${Grammar.Regex.Symbol.source})\\s*\\(\\s*`),
|
||||
1
|
||||
),
|
||||
static grammar = /** @type {P<UnknownPinEntity>} */(
|
||||
P.seq(
|
||||
P.reg(new RegExp(`(${Grammar.Regex.Symbol.source})\\s*\\(\\s*`), 1),
|
||||
Grammar.createAttributeGrammar(this).sepBy(Grammar.commaSeparation),
|
||||
Parsernostrum.reg(/\s*(?:,\s*)?\)/)
|
||||
P.reg(/\s*(?:,\s*)?\)/)
|
||||
).map(([lookbehind, attributes, _2]) => {
|
||||
lookbehind ??= ""
|
||||
let values = {}
|
||||
@@ -22,10 +17,6 @@ export default class UnknownPinEntity extends PinEntity {
|
||||
}
|
||||
attributes.forEach(attributeSetter => attributeSetter(values))
|
||||
return new this(values)
|
||||
})
|
||||
}
|
||||
|
||||
constructor(values = {}) {
|
||||
super(values, true)
|
||||
}
|
||||
}).label("UnknownPinEntity")
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import BooleanEntity from "./BooleanEntity.js"
|
||||
import GuidEntity from "./GuidEntity.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
import StringEntity from "./StringEntity.js"
|
||||
|
||||
export default class VariableReferenceEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
MemberScope: AttributeInfo.createType(String),
|
||||
MemberName: AttributeInfo.createValue(""),
|
||||
MemberGuid: AttributeInfo.createType(GuidEntity),
|
||||
bSelfContext: AttributeInfo.createType(Boolean),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.createEntityGrammar(this)
|
||||
MemberScope: StringEntity,
|
||||
MemberName: StringEntity.withDefault(),
|
||||
MemberGuid: GuidEntity,
|
||||
bSelfContext: BooleanEntity,
|
||||
}
|
||||
static grammar = /** @type {P<VariableReferenceEntity>} */(
|
||||
Grammar.createEntityGrammar(this).label("VariableReferenceEntity")
|
||||
)
|
||||
|
||||
constructor(values) {
|
||||
super(values)
|
||||
/** @type {String} */ this.MemberName
|
||||
/** @type {GuidEntity} */ this.GuidEntity
|
||||
/** @type {Boolean} */ this.bSelfContext
|
||||
/** @type {InstanceType<typeof VariableReferenceEntity.attributes.MemberScope>} */ this.MemberScope
|
||||
/** @type {InstanceType<typeof VariableReferenceEntity.attributes.MemberName>} */ this.MemberName
|
||||
/** @type {InstanceType<typeof VariableReferenceEntity.attributes.MemberGuid>} */ this.MemberGuid
|
||||
/** @type {InstanceType<typeof VariableReferenceEntity.attributes.bSelfContext>} */ this.bSelfContext
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,27 @@
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
import NumberEntity from "./NumberEntity.js"
|
||||
|
||||
export default class Vector2DEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
X: new AttributeInfo({
|
||||
default: 0,
|
||||
expected: true,
|
||||
}),
|
||||
Y: new AttributeInfo({
|
||||
default: 0,
|
||||
expected: true,
|
||||
}),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.createEntityGrammar(this, false)
|
||||
X: NumberEntity.withDefault(),
|
||||
Y: NumberEntity.withDefault(),
|
||||
}
|
||||
static grammar = /** @type {P<Vector2DEntity>} */(
|
||||
Grammar.createEntityGrammar(this, Grammar.commaSeparation, true).label("Vector2DEntity")
|
||||
)
|
||||
|
||||
constructor(values) {
|
||||
super(values)
|
||||
/** @type {Number} */ this.X
|
||||
/** @type {Number} */ this.Y
|
||||
/** @type {InstanceType<typeof Vector2DEntity.attributes.X>} */ this.X
|
||||
/** @type {InstanceType<typeof Vector2DEntity.attributes.Y>} */ this.Y
|
||||
}
|
||||
|
||||
/** @returns {[Number, Number]} */
|
||||
toArray() {
|
||||
return [this.X, this.Y]
|
||||
return [this.X.valueOf(), this.Y.valueOf()]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,31 @@
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
import NumberEntity from "./NumberEntity.js"
|
||||
|
||||
export default class Vector4DEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
X: new AttributeInfo({
|
||||
default: 0,
|
||||
expected: true,
|
||||
}),
|
||||
Y: new AttributeInfo({
|
||||
default: 0,
|
||||
expected: true,
|
||||
}),
|
||||
Z: new AttributeInfo({
|
||||
default: 0,
|
||||
expected: true,
|
||||
}),
|
||||
W: new AttributeInfo({
|
||||
default: 0,
|
||||
expected: true,
|
||||
}),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.createEntityGrammar(Vector4DEntity, false)
|
||||
X: NumberEntity.withDefault(),
|
||||
Y: NumberEntity.withDefault(),
|
||||
Z: NumberEntity.withDefault(),
|
||||
W: NumberEntity.withDefault(),
|
||||
}
|
||||
static grammar = /** @type {P<Vector4DEntity>} */(
|
||||
Grammar.createEntityGrammar(this, Grammar.commaSeparation, true).label("Vector4DEntity")
|
||||
)
|
||||
|
||||
constructor(values) {
|
||||
super(values)
|
||||
/** @type {Number} */ this.X
|
||||
/** @type {Number} */ this.Y
|
||||
/** @type {Number} */ this.Z
|
||||
/** @type {Number} */ this.W
|
||||
/** @type {InstanceType<typeof Vector4DEntity.attributes.X>} */ this.X
|
||||
/** @type {InstanceType<typeof Vector4DEntity.attributes.Y>} */ this.Y
|
||||
/** @type {InstanceType<typeof Vector4DEntity.attributes.Z>} */ this.Z
|
||||
/** @type {InstanceType<typeof Vector4DEntity.attributes.W>} */ this.W
|
||||
}
|
||||
|
||||
/** @returns {[Number, Number, Number, Number]} */
|
||||
toArray() {
|
||||
return [this.X, this.Y, this.Z, this.W]
|
||||
return [this.X.valueOf(), this.Y.valueOf(), this.Z.valueOf(), this.W.valueOf()]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,29 @@
|
||||
import P from "parsernostrum"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import AttributeInfo from "./AttributeInfo.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
import NumberEntity from "./NumberEntity.js"
|
||||
|
||||
export default class VectorEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
...super.attributes,
|
||||
X: new AttributeInfo({
|
||||
default: 0,
|
||||
expected: true,
|
||||
}),
|
||||
Y: new AttributeInfo({
|
||||
default: 0,
|
||||
expected: true,
|
||||
}),
|
||||
Z: new AttributeInfo({
|
||||
default: 0,
|
||||
expected: true,
|
||||
}),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.createEntityGrammar(VectorEntity, false)
|
||||
X: NumberEntity.withDefault(),
|
||||
Y: NumberEntity.withDefault(),
|
||||
Z: NumberEntity.withDefault(),
|
||||
}
|
||||
static grammar = /** @type {P<VectorEntity>} */(
|
||||
Grammar.createEntityGrammar(this, Grammar.commaSeparation, true).label("VectorEntity")
|
||||
)
|
||||
|
||||
constructor(values) {
|
||||
super(values)
|
||||
/** @type {Number} */ this.X
|
||||
/** @type {Number} */ this.Y
|
||||
/** @type {Number} */ this.Z
|
||||
/** @type {InstanceType<typeof VectorEntity.attributes.X>} */ this.X
|
||||
/** @type {InstanceType<typeof VectorEntity.attributes.Y>} */ this.Y
|
||||
/** @type {InstanceType<typeof VectorEntity.attributes.X>} */ this.Z
|
||||
}
|
||||
|
||||
/** @returns {[Number, Number, Number]} */
|
||||
toArray() {
|
||||
return [this.X, this.Y, this.Z]
|
||||
return [this.X.valueOf(), this.Y.valueOf(), this.Z.valueOf()]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,20 +14,18 @@ export default class KnotEntity extends ObjectEntity {
|
||||
values.Name = "K2Node_Knot"
|
||||
const inputPinEntity = new PinEntity(
|
||||
{ PinName: "InputPin" },
|
||||
true
|
||||
)
|
||||
const outputPinEntity = new PinEntity(
|
||||
{
|
||||
PinName: "OutputPin",
|
||||
Direction: "EGPD_Output",
|
||||
},
|
||||
true
|
||||
)
|
||||
if (pinReferenceForType) {
|
||||
inputPinEntity.copyTypeFrom(pinReferenceForType)
|
||||
outputPinEntity.copyTypeFrom(pinReferenceForType)
|
||||
}
|
||||
values["CustomProperties"] = [inputPinEntity, outputPinEntity]
|
||||
super(values, true)
|
||||
super(values)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import ObjectSerializer from "../../serialization/ObjectSerializer.js"
|
||||
import IInput from "../IInput.js"
|
||||
|
||||
/**
|
||||
@@ -10,8 +9,6 @@ import IInput from "../IInput.js"
|
||||
|
||||
export default class Copy extends IInput {
|
||||
|
||||
static #serializer = new ObjectSerializer()
|
||||
|
||||
/** @type {(e: ClipboardEvent) => void} */
|
||||
#copyHandler
|
||||
|
||||
@@ -33,11 +30,11 @@ export default class Copy extends IInput {
|
||||
|
||||
getSerializedText() {
|
||||
const allNodes = this.blueprint.getNodes(true).map(n => n.entity)
|
||||
const exported = allNodes.filter(n => n.isExported).map(n => Copy.#serializer.write(n, false))
|
||||
const result = allNodes.filter(n => !n.isExported).map(n => Copy.#serializer.write(n, false))
|
||||
const exported = allNodes.filter(n => n.exported).map(n => n.toString())
|
||||
const result = allNodes.filter(n => !n.exported).map(n => n.toString())
|
||||
if (exported.length) {
|
||||
this.blueprint.entity.ExportedNodes = btoa(exported.join(""))
|
||||
result.splice(0, 0, Copy.#serializer.write(this.blueprint.entity, false))
|
||||
result.splice(0, 0, this.blueprint.entity.toString(false))
|
||||
delete this.blueprint.entity.ExportedNodes
|
||||
}
|
||||
return result.join("")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import ObjectSerializer from "../../serialization/ObjectSerializer.js"
|
||||
import IInput from "../IInput.js"
|
||||
|
||||
/**
|
||||
@@ -10,8 +9,6 @@ import IInput from "../IInput.js"
|
||||
|
||||
export default class Cut extends IInput {
|
||||
|
||||
static #serializer = new ObjectSerializer()
|
||||
|
||||
/** @type {(e: ClipboardEvent) => void} */
|
||||
#cutHandler
|
||||
|
||||
@@ -39,7 +36,7 @@ export default class Cut extends IInput {
|
||||
getSerializedText() {
|
||||
return this.blueprint
|
||||
.getNodes(true)
|
||||
.map(node => Cut.#serializer.write(node.entity, false))
|
||||
.map(node => node.entity.toString())
|
||||
.join("")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import ElementFactory from "../../element/ElementFactory.js"
|
||||
import ObjectEntity from "../../entity/ObjectEntity.js"
|
||||
import IInput from "../IInput.js"
|
||||
import ObjectSerializer from "../../serialization/ObjectSerializer.js"
|
||||
|
||||
/**
|
||||
* @typedef {import("../IInput.js").Options & {
|
||||
@@ -11,8 +11,6 @@ import ObjectSerializer from "../../serialization/ObjectSerializer.js"
|
||||
|
||||
export default class Paste extends IInput {
|
||||
|
||||
static #serializer = new ObjectSerializer()
|
||||
|
||||
/** @type {(e: ClipboardEvent) => void} */
|
||||
#pasteHandle
|
||||
|
||||
@@ -42,7 +40,7 @@ export default class Paste extends IInput {
|
||||
let top = 0
|
||||
let left = 0
|
||||
let count = 0
|
||||
let nodes = Paste.#serializer.readMultiple(value).map(entity => {
|
||||
let nodes = ObjectEntity.grammarMultipleObjects.parse(value).map(entity => {
|
||||
let node = /** @type {NodeElementConstructor} */(ElementFactory.getConstructor("ueb-node"))
|
||||
.newObject(entity)
|
||||
top += node.locationY
|
||||
|
||||
@@ -64,9 +64,12 @@ export default class KeyboardShortcut extends IInput {
|
||||
|
||||
this.#activationKeys = this.options.activationKeys ?? []
|
||||
|
||||
const wantsShift = keyEntry => keyEntry.bShift || keyEntry.Key == "LeftShift" || keyEntry.Key == "RightShift"
|
||||
const wantsCtrl = keyEntry => keyEntry.bCtrl || keyEntry.Key == "LeftControl" || keyEntry.Key == "RightControl"
|
||||
const wantsAlt = keyEntry => keyEntry.bAlt || keyEntry.Key == "LeftAlt" || keyEntry.Key == "RightAlt"
|
||||
/** @param {KeyBindingEntity} keyEntry */
|
||||
const wantsShift = keyEntry => keyEntry.bShift?.valueOf() || keyEntry.Key.valueOf() == "LeftShift" || keyEntry.Key.valueOf() == "RightShift"
|
||||
/** @param {KeyBindingEntity} keyEntry */
|
||||
const wantsCtrl = keyEntry => keyEntry.bCtrl?.valueOf() || keyEntry.Key.valueOf() == "LeftControl" || keyEntry.Key.valueOf() == "RightControl"
|
||||
/** @param {KeyBindingEntity} keyEntry */
|
||||
const wantsAlt = keyEntry => keyEntry.bAlt?.valueOf() || keyEntry.Key.valueOf() == "LeftAlt" || keyEntry.Key.valueOf() == "RightAlt"
|
||||
|
||||
let self = this
|
||||
/** @param {KeyboardEvent} e */
|
||||
@@ -94,10 +97,10 @@ export default class KeyboardShortcut extends IInput {
|
||||
this.keyUpHandler = e => {
|
||||
if (
|
||||
self.#activationKeys.some(keyEntry =>
|
||||
keyEntry.bShift && e.key == "Shift"
|
||||
|| keyEntry.bCtrl && e.key == "Control"
|
||||
|| keyEntry.bAlt && e.key == "Alt"
|
||||
|| keyEntry.bCmd && e.key == "Meta"
|
||||
keyEntry.bShift?.valueOf() && e.key == "Shift"
|
||||
|| keyEntry.bCtrl?.valueOf() && e.key == "Control"
|
||||
|| keyEntry.bAlt?.valueOf() && e.key == "Alt"
|
||||
|| keyEntry.bCmd?.valueOf() && e.key == "Meta"
|
||||
|| Configuration.Keys[keyEntry.Key.value] == e.code
|
||||
)
|
||||
) {
|
||||
|
||||
@@ -43,7 +43,7 @@ export default class MouseCreateLink extends IMouseClickDrag {
|
||||
this.link.setMessageReplaceOutputLink()
|
||||
this.linkValid = true
|
||||
} else if (
|
||||
(a.entity.PinType.PinCategory != "object" || b.entity.PinType.PinCategory != "object")
|
||||
(a.entity.PinType.PinCategory.valueOf() != "object" || b.entity.PinType.PinCategory.valueOf() != "object")
|
||||
&& a.pinType != b.pinType
|
||||
) {
|
||||
this.link.setMessageTypesIncompatible(a, b)
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import Serializer from "./Serializer.js"
|
||||
|
||||
/**
|
||||
* @template {AttributeConstructor<Attribute>} T
|
||||
* @extends {Serializer<T>}
|
||||
*/
|
||||
export default class CustomSerializer extends Serializer {
|
||||
|
||||
#objectWriter
|
||||
|
||||
/**
|
||||
* @param {(v: ConstructedType<T>, insideString: Boolean) => String} objectWriter
|
||||
* @param {T} entityType
|
||||
*/
|
||||
constructor(objectWriter, entityType) {
|
||||
super(entityType)
|
||||
this.#objectWriter = objectWriter
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ConstructedType<T>} entity
|
||||
* @param {Boolean} insideString
|
||||
* @returns {String}
|
||||
*/
|
||||
doWrite(entity, insideString, indentation = "") {
|
||||
let result = this.#objectWriter(entity, insideString)
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import Configuration from "../Configuration.js"
|
||||
import Utility from "../Utility.js"
|
||||
import AttributeInfo from "../entity/AttributeInfo.js"
|
||||
import AlternativesEntity from "../entity/AlternativesEntity.js"
|
||||
import IEntity from "../entity/IEntity.js"
|
||||
import MirroredEntity from "../entity/MirroredEntity.js"
|
||||
import Union from "../entity/Union.js"
|
||||
import Serializable from "./Serializable.js"
|
||||
|
||||
export default class Grammar {
|
||||
|
||||
/** @type {String} */
|
||||
// @ts-expect-error
|
||||
static numberRegexSource = Parsernostrum.number.getParser().parser.regexp.source
|
||||
|
||||
static separatedBy = (source, separator, min = 1) =>
|
||||
new RegExp(
|
||||
source + "(?:" + separator + source + ")"
|
||||
@@ -36,7 +37,6 @@ export default class Grammar {
|
||||
static null = Parsernostrum.reg(/\(\s*\)/).map(() => null)
|
||||
static true = Parsernostrum.reg(/true/i).map(() => true)
|
||||
static false = Parsernostrum.reg(/false/i).map(() => false)
|
||||
static boolean = Parsernostrum.regArray(/(true)|false/i).map(v => v[1] ? true : false)
|
||||
static number = Parsernostrum.regArray(
|
||||
new RegExp(`(${Parsernostrum.number.getParser().parser.regexp.source})|(\\+?inf)|(-inf)`)
|
||||
).map(([_0, n, plusInf, minusInf]) => n ? Number(n) : plusInf ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY)
|
||||
@@ -68,103 +68,36 @@ export default class Grammar {
|
||||
/* --- Factory --- */
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {AttributeInfo<T>} attribute
|
||||
* @param {Parsernostrum<any>} defaultGrammar
|
||||
* @returns {Parsernostrum<T>}
|
||||
* @param {typeof IEntity} entityType
|
||||
* @param {String[]} key
|
||||
* @returns {typeof IEntity}
|
||||
*/
|
||||
static grammarFor(attribute, type = attribute?.type, defaultGrammar = this.unknownValue) {
|
||||
let result = defaultGrammar
|
||||
if (type === Array || type instanceof Array) {
|
||||
if (attribute?.inlined) {
|
||||
return this.grammarFor(undefined, type[0])
|
||||
}
|
||||
result = Parsernostrum.seq(
|
||||
Parsernostrum.reg(/\(\s*/),
|
||||
this.grammarFor(undefined, type[0]).sepBy(this.commaSeparation).opt(),
|
||||
Parsernostrum.reg(/\s*(?:,\s*)?\)/),
|
||||
).map(([_0, values, _3]) => values instanceof Array ? values : [])
|
||||
} else if (type instanceof Union) {
|
||||
result = type.values
|
||||
.map(v => this.grammarFor(undefined, v))
|
||||
.reduce((acc, cur) => !cur || cur === this.unknownValue || acc === this.unknownValue
|
||||
? this.unknownValue
|
||||
: Parsernostrum.alt(acc, cur)
|
||||
)
|
||||
} else if (type instanceof MirroredEntity) {
|
||||
// @ts-expect-error
|
||||
return this.grammarFor(undefined, type.getTargetType())
|
||||
.map(v => new MirroredEntity(type.type, () => v))
|
||||
} else if (attribute?.constructor === Object) {
|
||||
result = this.grammarFor(undefined, type)
|
||||
} else {
|
||||
switch (type) {
|
||||
case Boolean:
|
||||
result = this.boolean
|
||||
break
|
||||
case null:
|
||||
result = this.null
|
||||
break
|
||||
case Number:
|
||||
result = this.number
|
||||
break
|
||||
case BigInt:
|
||||
result = this.bigInt
|
||||
break
|
||||
case String:
|
||||
result = this.string
|
||||
break
|
||||
default:
|
||||
if (/** @type {AttributeConstructor<any>} */(type)?.prototype instanceof Serializable) {
|
||||
result = /** @type {typeof Serializable} */(type).grammar
|
||||
}
|
||||
}
|
||||
static getAttribute(entityType, [key, ...keys]) {
|
||||
const attribute = entityType?.attributes?.[key]
|
||||
if (!attribute) {
|
||||
return
|
||||
}
|
||||
if (attribute) {
|
||||
if (attribute.serialized && type.constructor !== String) {
|
||||
if (result == this.unknownValue) {
|
||||
result = this.string
|
||||
} else {
|
||||
result = Parsernostrum.seq(Parsernostrum.str('"'), result, Parsernostrum.str('"')).map(([_0, value, _2]) => value)
|
||||
if (attribute.prototype instanceof AlternativesEntity) {
|
||||
for (const alternative of /** @type {typeof AlternativesEntity} */(attribute).alternatives) {
|
||||
const candidate = this.getAttribute(alternative, keys)
|
||||
if (candidate) {
|
||||
return candidate
|
||||
}
|
||||
}
|
||||
if (attribute.nullable) {
|
||||
result = Parsernostrum.alt(result, this.null)
|
||||
}
|
||||
}
|
||||
return result
|
||||
if (keys.length > 0) {
|
||||
return this.getAttribute(attribute, keys)
|
||||
}
|
||||
return attribute
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {AttributeConstructor<Attribute>} T
|
||||
* @param {T} entityType
|
||||
* @param {String[]} key
|
||||
* @returns {AttributeInfo}
|
||||
* @param {typeof IEntity} entityType
|
||||
* @param {*} attributeName
|
||||
* @param {*} valueSeparator
|
||||
* @param {*} handleObjectSet
|
||||
* @returns
|
||||
*/
|
||||
static getAttribute(entityType, key) {
|
||||
let result
|
||||
let type
|
||||
if (entityType instanceof Union) {
|
||||
for (let t of entityType.values) {
|
||||
if (result = this.getAttribute(t, key)) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
if (entityType instanceof IEntity.constructor) {
|
||||
// @ts-expect-error
|
||||
result = entityType.attributes[key[0]]
|
||||
type = result?.type
|
||||
} else if (entityType instanceof Array) {
|
||||
result = entityType[key[0]]
|
||||
type = result
|
||||
}
|
||||
if (key.length > 1) {
|
||||
return this.getAttribute(type, key.slice(1))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
static createAttributeGrammar(
|
||||
entityType,
|
||||
attributeName = this.attributeName,
|
||||
@@ -177,64 +110,47 @@ export default class Grammar {
|
||||
).chain(([attributeName, _1]) => {
|
||||
const attributeKey = attributeName.split(Configuration.keysSeparator)
|
||||
const attributeValue = this.getAttribute(entityType, attributeKey)
|
||||
return this
|
||||
.grammarFor(attributeValue)
|
||||
.map(attributeValue =>
|
||||
values => {
|
||||
handleObjectSet(values, attributeKey, attributeValue)
|
||||
Utility.objectSet(values, attributeKey, attributeValue)
|
||||
}
|
||||
)
|
||||
return (attributeValue?.grammar ?? IEntity.unknownEntityGrammar).map(attributeValue =>
|
||||
values => {
|
||||
handleObjectSet(values, attributeKey, attributeValue)
|
||||
Utility.objectSet(values, attributeKey, attributeValue)
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {IEntity} T
|
||||
* @param {(new (...args: any) => T) & EntityConstructor} entityType
|
||||
* @param {Boolean | Number} acceptUnknownKeys Number to specify the limit or true, to let it be a reasonable value
|
||||
* @template {typeof IEntity} T
|
||||
* @param {T} entityType
|
||||
* @return {Parsernostrum<InstanceType<T>>}
|
||||
*/
|
||||
static createEntityGrammar(entityType, acceptUnknownKeys = true, entriesSeparator = this.commaSeparation) {
|
||||
const lookbehind = entityType.attributes.lookbehind.default
|
||||
static createEntityGrammar(entityType, entriesSeparator = this.commaSeparation, complete = false, minKeys = 1) {
|
||||
const lookbehind = entityType.lookbehind instanceof Array ? entityType.lookbehind.join("|") : entityType.lookbehind
|
||||
return Parsernostrum.seq(
|
||||
Parsernostrum.reg(
|
||||
lookbehind instanceof Union
|
||||
? new RegExp(`(${lookbehind.values.reduce((acc, cur) => acc + "|" + cur)})\\s*\\(\\s*`)
|
||||
: lookbehind.constructor == String && lookbehind.length > 0
|
||||
? new RegExp(`(${lookbehind})\\s*\\(\\s*`)
|
||||
: /()\(\s*/,
|
||||
1
|
||||
),
|
||||
this.createAttributeGrammar(entityType).sepBy(entriesSeparator),
|
||||
Parsernostrum.reg(/\s*(?:,\s*)?\)/), // trailing comma
|
||||
Parsernostrum.reg(new RegExp(String.raw`(${lookbehind}\s*)\(\s*`), 1),
|
||||
this.createAttributeGrammar(entityType).sepBy(entriesSeparator, minKeys),
|
||||
Parsernostrum.reg(/\s*(,\s*)?\)/, 1), // optional trailing comma
|
||||
)
|
||||
.map(([lookbehind, attributes, _2]) => {
|
||||
.map(([lookbehind, attributes, trailing]) => {
|
||||
let values = {}
|
||||
attributes.forEach(attributeSetter => attributeSetter(values))
|
||||
if (lookbehind.length) {
|
||||
values.lookbehind = lookbehind
|
||||
values["lookbehind"] = lookbehind
|
||||
}
|
||||
attributes.forEach(attributeSetter => attributeSetter(values))
|
||||
values["trailing"] = trailing !== undefined
|
||||
return values
|
||||
})
|
||||
// Decide if we accept the entity or not. It is accepted if it doesn't have too many unexpected keys
|
||||
.chain(values => {
|
||||
let totalKeys = Object.keys(values)
|
||||
let missingKey
|
||||
// Check missing values
|
||||
if (
|
||||
Object.keys(/** @type {AttributeDeclarations} */(entityType.attributes))
|
||||
.filter(key => entityType.attributes[key].expected)
|
||||
.find(key => !totalKeys.includes(key) && (missingKey = key))
|
||||
) {
|
||||
return Parsernostrum.failure()
|
||||
if (entityType.lookbehind instanceof Array || entityType.lookbehind !== lookbehind) {
|
||||
entityType = entityType.withLookbehind(lookbehind)
|
||||
}
|
||||
const unknownKeys = Object.keys(values).filter(key => !(key in entityType.attributes)).length
|
||||
if (!acceptUnknownKeys && unknownKeys > 0) {
|
||||
return Parsernostrum.failure()
|
||||
}
|
||||
return Parsernostrum.success().map(() => new entityType(values))
|
||||
const keys = Object.keys(values)
|
||||
return complete
|
||||
? Parsernostrum.success()
|
||||
.assert(v => Object.keys(entityType.attributes).every(k => keys.includes(k)))
|
||||
.map(() => new entityType(values))
|
||||
: Parsernostrum.success().map(() => new entityType(values))
|
||||
})
|
||||
}
|
||||
|
||||
/** @type {Parsernostrum<any>} */
|
||||
static unknownValue // Defined in initializeSerializerFactor to avoid circular include
|
||||
}
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
import Configuration from "../Configuration.js"
|
||||
import AttributeInfo from "../entity/AttributeInfo.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"
|
||||
|
||||
/** @extends Serializer<ObjectEntityConstructor> */
|
||||
export default class ObjectSerializer extends Serializer {
|
||||
|
||||
constructor(entityType = ObjectEntity) {
|
||||
super(entityType, undefined, "\n", true, undefined, Serializer.same)
|
||||
}
|
||||
|
||||
showProperty(entity, key) {
|
||||
switch (key) {
|
||||
case "Class":
|
||||
case "Name":
|
||||
case "Archetype":
|
||||
case "ExportPath":
|
||||
case "CustomProperties":
|
||||
// Serielized separately, check doWrite()
|
||||
return false
|
||||
}
|
||||
return super.showProperty(entity, key)
|
||||
}
|
||||
|
||||
/** @param {ObjectEntity} value */
|
||||
write(value, insideString = false) {
|
||||
return this.doWrite(value, insideString) + "\n"
|
||||
}
|
||||
|
||||
/** @param {String} value */
|
||||
doRead(value) {
|
||||
return Grammar.grammarFor(undefined, this.entityType).parse(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} value
|
||||
* @returns {ObjectEntity[]}
|
||||
*/
|
||||
readMultiple(value) {
|
||||
return ObjectEntity.getMultipleObjectsGrammar().parse(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ObjectEntity} entity
|
||||
* @param {Boolean} insideString
|
||||
* @returns {String}
|
||||
*/
|
||||
doWrite(
|
||||
entity,
|
||||
insideString,
|
||||
indentation = "",
|
||||
wrap = this.wrap,
|
||||
attributeSeparator = this.attributeSeparator,
|
||||
trailingSeparator = this.trailingSeparator,
|
||||
attributeValueConjunctionSign = this.attributeValueConjunctionSign,
|
||||
attributeKeyPrinter = this.attributeKeyPrinter,
|
||||
) {
|
||||
const moreIndentation = indentation + Configuration.indentation
|
||||
if (!(entity instanceof ObjectEntity)) {
|
||||
return super.doWrite(
|
||||
entity,
|
||||
insideString,
|
||||
indentation,
|
||||
wrap,
|
||||
attributeSeparator,
|
||||
trailingSeparator,
|
||||
attributeValueConjunctionSign,
|
||||
// @ts-expect-error
|
||||
key => entity[key] instanceof ObjectEntity ? "" : attributeKeyPrinter(key)
|
||||
)
|
||||
}
|
||||
let result = indentation + "Begin Object"
|
||||
+ (entity.Class?.type || entity.Class?.path ? ` Class=${this.doWriteValue(entity.Class, insideString)}` : "")
|
||||
+ (entity.Name ? ` Name=${this.doWriteValue(entity.Name, insideString)}` : "")
|
||||
+ (entity.Archetype ? ` Archetype=${this.doWriteValue(entity.Archetype, insideString)}` : "")
|
||||
+ (entity.ExportPath?.type || entity.ExportPath?.path ? ` ExportPath=${this.doWriteValue(entity.ExportPath, insideString)}` : "")
|
||||
+ "\n"
|
||||
+ super.doWrite(
|
||||
entity,
|
||||
insideString,
|
||||
moreIndentation,
|
||||
wrap,
|
||||
attributeSeparator,
|
||||
true,
|
||||
attributeValueConjunctionSign,
|
||||
key => entity[key] instanceof ObjectEntity ? "" : attributeKeyPrinter(key)
|
||||
)
|
||||
+ (!AttributeInfo.getAttribute(entity, "CustomProperties", "ignored")
|
||||
? entity.getCustomproperties().map(pin =>
|
||||
moreIndentation
|
||||
+ attributeKeyPrinter("CustomProperties ")
|
||||
+ SerializerFactory.getSerializer(PinEntity).doWrite(pin, insideString)
|
||||
+ this.attributeSeparator
|
||||
).join("")
|
||||
: ""
|
||||
)
|
||||
+ indentation + "End Object"
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
|
||||
export default class Serializable {
|
||||
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
/** @protected */
|
||||
static createGrammar() {
|
||||
return /** @type {Parsernostrum<any>} */(Parsernostrum.failure())
|
||||
}
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
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 {
|
||||
|
||||
/** @type {(v: String) => String} */
|
||||
static same = v => v
|
||||
|
||||
/** @type {(entity: Attribute, serialized: String) => String} */
|
||||
static notWrapped = (entity, serialized) => serialized
|
||||
|
||||
/** @type {(entity: Attribute, serialized: String) => String} */
|
||||
static bracketsWrapped = (entity, serialized) => `(${serialized})`
|
||||
|
||||
/** @param {T} entityType */
|
||||
constructor(
|
||||
entityType,
|
||||
/** @type {(entity: ConstructedType<T>, serialized: String) => String} */
|
||||
wrap = (entity, serialized) => serialized,
|
||||
attributeSeparator = ",",
|
||||
trailingSeparator = false,
|
||||
attributeValueConjunctionSign = "=",
|
||||
attributeKeyPrinter = Serializer.same
|
||||
) {
|
||||
this.entityType = entityType
|
||||
this.wrap = wrap
|
||||
this.attributeSeparator = attributeSeparator
|
||||
this.trailingSeparator = trailingSeparator
|
||||
this.attributeValueConjunctionSign = attributeValueConjunctionSign
|
||||
this.attributeKeyPrinter = attributeKeyPrinter
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} value
|
||||
* @returns {ConstructedType<T>}
|
||||
*/
|
||||
read(value) {
|
||||
return this.doRead(value.trim())
|
||||
}
|
||||
|
||||
/** @param {ConstructedType<T>} value */
|
||||
write(value, insideString = false) {
|
||||
return this.doWrite(value, insideString)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} value
|
||||
* @returns {ConstructedType<T>}
|
||||
*/
|
||||
doRead(value) {
|
||||
let grammar = Grammar.grammarFor(undefined, this.entityType)
|
||||
const parseResult = grammar.run(value)
|
||||
if (!parseResult.status) {
|
||||
throw new Error(
|
||||
this.entityType
|
||||
? `Error when trying to parse the entity ${this.entityType.prototype.constructor.name}`
|
||||
: "Error when trying to parse null"
|
||||
)
|
||||
}
|
||||
return parseResult.value
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ConstructedType<T>} entity
|
||||
* @param {Boolean} insideString
|
||||
* @returns {String}
|
||||
*/
|
||||
doWrite(
|
||||
entity,
|
||||
insideString = false,
|
||||
indentation = "",
|
||||
wrap = this.wrap,
|
||||
attributeSeparator = this.attributeSeparator,
|
||||
trailingSeparator = this.trailingSeparator,
|
||||
attributeValueConjunctionSign = this.attributeValueConjunctionSign,
|
||||
attributeKeyPrinter = this.attributeKeyPrinter
|
||||
) {
|
||||
let result = ""
|
||||
const keys = entity._keys ?? Object.keys(entity)
|
||||
let first = true
|
||||
for (const key of keys) {
|
||||
const value = entity[key]
|
||||
if (value !== undefined && this.showProperty(entity, key)) {
|
||||
let keyValue = entity instanceof Array ? `(${key})` : key
|
||||
if (AttributeInfo.getAttribute(entity, key, "quoted")) {
|
||||
keyValue = `"${keyValue}"`
|
||||
}
|
||||
const isSerialized = AttributeInfo.getAttribute(entity, key, "serialized")
|
||||
if (first) {
|
||||
first = false
|
||||
} else {
|
||||
result += attributeSeparator
|
||||
}
|
||||
if (AttributeInfo.getAttribute(entity, key, "inlined")) {
|
||||
result += this.doWrite(
|
||||
value,
|
||||
insideString,
|
||||
indentation,
|
||||
Serializer.notWrapped,
|
||||
attributeSeparator,
|
||||
false,
|
||||
attributeValueConjunctionSign,
|
||||
AttributeInfo.getAttribute(entity, key, "type") instanceof Array
|
||||
? k => attributeKeyPrinter(`${keyValue}${k}`)
|
||||
: k => attributeKeyPrinter(`${keyValue}.${k}`)
|
||||
)
|
||||
continue
|
||||
}
|
||||
const keyPrinted = attributeKeyPrinter(keyValue)
|
||||
const indentationPrinted = attributeSeparator.includes("\n") ? indentation : ""
|
||||
result += (
|
||||
keyPrinted.length
|
||||
? (indentationPrinted + keyPrinted + this.attributeValueConjunctionSign)
|
||||
: ""
|
||||
)
|
||||
+ (
|
||||
isSerialized
|
||||
? `"${this.doWriteValue(value, true, indentation)}"`
|
||||
: this.doWriteValue(value, insideString, indentation)
|
||||
)
|
||||
}
|
||||
}
|
||||
if (trailingSeparator && result.length) {
|
||||
// append separator at the end if asked and there was printed content
|
||||
result += attributeSeparator
|
||||
}
|
||||
return wrap(entity, result)
|
||||
}
|
||||
|
||||
/** @param {Boolean} insideString */
|
||||
doWriteValue(value, insideString, indentation = "") {
|
||||
const type = Utility.getType(value)
|
||||
const serializer = SerializerFactory.getSerializer(type)
|
||||
if (!serializer) {
|
||||
throw new Error(
|
||||
`Unknown value type "${type.name}", a serializer must be registered in the SerializerFactory class, `
|
||||
+ "check initializeSerializerFactory.js"
|
||||
)
|
||||
}
|
||||
return serializer.doWrite(value, insideString, indentation)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {IEntity} entity
|
||||
* @param {String} key
|
||||
*/
|
||||
showProperty(entity, key) {
|
||||
if (entity instanceof IEntity) {
|
||||
if (AttributeInfo.getAttribute(entity, key, "ignored")) {
|
||||
return false
|
||||
}
|
||||
if (AttributeInfo.getAttribute(entity, key, "silent")) {
|
||||
let defaultValue = AttributeInfo.getAttribute(entity, key, "default")
|
||||
if (defaultValue instanceof Function) {
|
||||
defaultValue = defaultValue(entity)
|
||||
}
|
||||
if (Utility.equals(entity[key], defaultValue)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
export default class SerializerFactory {
|
||||
|
||||
static #serializers = new Map()
|
||||
|
||||
/**
|
||||
* @template {AttributeConstructor<Attribute>} T
|
||||
* @param {T} type
|
||||
* @param {Serializer<T>} object
|
||||
*/
|
||||
static registerSerializer(type, object) {
|
||||
SerializerFactory.#serializers.set(type, object)
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {AttributeConstructor<Attribute>} T
|
||||
* @param {T} type
|
||||
* @returns {Serializer<T>}
|
||||
*/
|
||||
static getSerializer(type) {
|
||||
return SerializerFactory.#serializers.get(type)
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import Utility from "../Utility.js"
|
||||
import Serializer from "./Serializer.js"
|
||||
|
||||
/**
|
||||
* @template {AttributeConstructor<Attribute>} T
|
||||
* @extends {Serializer<T>}
|
||||
*/
|
||||
export default class ToStringSerializer extends Serializer {
|
||||
|
||||
/** @param {T} entityType */
|
||||
constructor(entityType, escape = true) {
|
||||
super(entityType)
|
||||
if (escape) {
|
||||
this.wrap = (entity, serialized) => Utility.escapeString(serialized)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ConstructedType<T>} entity
|
||||
* @param {Boolean} insideString
|
||||
*/
|
||||
doWrite(entity, insideString, indentation = "") {
|
||||
|
||||
return !insideString && entity.constructor === String
|
||||
? `"${this.wrap(entity, entity.toString())}"` // String will have quotes if not inside a string already
|
||||
: this.wrap(entity, entity.toString())
|
||||
}
|
||||
}
|
||||
@@ -1,342 +1,50 @@
|
||||
import Parsernostrum from "parsernostrum"
|
||||
import Utility from "../Utility.js"
|
||||
import BlueprintEntity from "../entity/BlueprintEntity.js"
|
||||
import ByteEntity from "../entity/ByteEntity.js"
|
||||
import ColorChannelEntity from "../entity/ColorChannelEntity.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 GuidEntity from "../entity/GuidEntity.js"
|
||||
import IdentifierEntity from "../entity/IdentifierEntity.js"
|
||||
import Integer64Entity from "../entity/Integer64Entity.js"
|
||||
import IntegerEntity from "../entity/IntegerEntity.js"
|
||||
import InvariantTextEntity from "../entity/InvariantTextEntity.js"
|
||||
import KeyBindingEntity from "../entity/KeyBindingEntity.js"
|
||||
import LinearColorEntity from "../entity/LinearColorEntity.js"
|
||||
import LocalizedTextEntity from "../entity/LocalizedTextEntity.js"
|
||||
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 PathSymbolEntity from "../entity/PathSymbolEntity.js"
|
||||
import PinEntity from "../entity/PinEntity.js"
|
||||
import PinReferenceEntity from "../entity/PinReferenceEntity.js"
|
||||
import PinTypeEntity from "../entity/PinTypeEntity.js"
|
||||
import RBSerializationVector2DEntity from "../entity/RBSerializationVector2DEntity.js"
|
||||
import RotatorEntity from "../entity/RotatorEntity.js"
|
||||
import ScriptVariableEntity from "../entity/ScriptVariableEntity.js"
|
||||
import SimpleSerializationRotatorEntity from "../entity/SimpleSerializationRotatorEntity.js"
|
||||
import SimpleSerializationVector2DEntity from "../entity/SimpleSerializationVector2DEntity.js"
|
||||
import SimpleSerializationVector4DEntity from "../entity/SimpleSerializationVector4DEntity.js"
|
||||
import SimpleSerializationVectorEntity from "../entity/SimpleSerializationVectorEntity.js"
|
||||
import SymbolEntity from "../entity/SymbolEntity.js"
|
||||
import TerminalTypeEntity from "../entity/TerminalTypeEntity.js"
|
||||
import Union from "../entity/Union.js"
|
||||
import UnknownKeysEntity from "../entity/UnknownKeysEntity.js"
|
||||
import VariableReferenceEntity from "../entity/VariableReferenceEntity.js"
|
||||
import Vector2DEntity from "../entity/Vector2DEntity.js"
|
||||
import Vector4DEntity from "../entity/Vector4DEntity.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"
|
||||
|
||||
Grammar.unknownValue =
|
||||
Parsernostrum.alt(
|
||||
// Remember to keep the order, otherwise parsing might fail
|
||||
Grammar.boolean,
|
||||
GuidEntity.grammar,
|
||||
Parsernostrum.str("None").map(() => new ObjectReferenceEntity({ type: "None" })),
|
||||
Grammar.null,
|
||||
Grammar.number,
|
||||
ObjectReferenceEntity.fullReferenceGrammar,
|
||||
Grammar.string,
|
||||
LocalizedTextEntity.grammar,
|
||||
InvariantTextEntity.grammar,
|
||||
FormatTextEntity.grammar,
|
||||
PinReferenceEntity.grammar,
|
||||
Vector4DEntity.grammar,
|
||||
VectorEntity.grammar,
|
||||
RotatorEntity.grammar,
|
||||
LinearColorEntity.grammar,
|
||||
Vector2DEntity.grammar,
|
||||
UnknownKeysEntity.grammar,
|
||||
SymbolEntity.grammar,
|
||||
Grammar.grammarFor(undefined, [PinReferenceEntity]),
|
||||
Grammar.grammarFor(undefined, [new Union(Number, String, SymbolEntity)]),
|
||||
Parsernostrum.lazy(() => Grammar.grammarFor(undefined, [undefined])),
|
||||
)
|
||||
import BooleanEntity from "../entity/BooleanEntity.js"
|
||||
import NumberEntity from "../entity/NumberEntity.js"
|
||||
import StringEntity from "../entity/StringEntity.js"
|
||||
import ArrayEntity from "../entity/ArrayEntity.js"
|
||||
import AlternativesEntity from "../entity/AlternativesEntity.js"
|
||||
import NullEntity from "../entity/NullEntity.js"
|
||||
import IEntity from "../entity/IEntity.js"
|
||||
|
||||
export default function initializeSerializerFactory() {
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
null,
|
||||
new CustomSerializer(
|
||||
(nullValue, insideString) => "()",
|
||||
null
|
||||
IEntity.unknownEntityGrammar =
|
||||
Parsernostrum.alt(
|
||||
// Remember to keep the order, otherwise parsing might fail
|
||||
BooleanEntity.grammar,
|
||||
GuidEntity.grammar,
|
||||
Parsernostrum.str("None").map(() => ObjectReferenceEntity.createNoneInstance()),
|
||||
NullEntity.grammar,
|
||||
NumberEntity.grammar,
|
||||
ObjectReferenceEntity.fullReferenceGrammar,
|
||||
StringEntity.grammar,
|
||||
LocalizedTextEntity.grammar,
|
||||
InvariantTextEntity.grammar,
|
||||
FormatTextEntity.grammar,
|
||||
PinReferenceEntity.grammar,
|
||||
Vector4DEntity.grammar,
|
||||
VectorEntity.grammar,
|
||||
Vector2DEntity.grammar,
|
||||
RotatorEntity.grammar,
|
||||
LinearColorEntity.grammar,
|
||||
UnknownKeysEntity.grammar,
|
||||
SymbolEntity.grammar,
|
||||
ArrayEntity.of(PinReferenceEntity).grammar,
|
||||
ArrayEntity.of(AlternativesEntity.accepting(NumberEntity, StringEntity, SymbolEntity)).grammar,
|
||||
Parsernostrum.lazy(() => ArrayEntity.createGrammar(IEntity.unknownEntityGrammar)),
|
||||
)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
Array,
|
||||
new CustomSerializer(
|
||||
(array, insideString) =>
|
||||
`(${array
|
||||
.map(v => SerializerFactory.getSerializer(Utility.getType(v)).write(v, insideString))
|
||||
.join(",")
|
||||
})`,
|
||||
Array
|
||||
)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
BigInt,
|
||||
new ToStringSerializer(BigInt)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
BlueprintEntity,
|
||||
new ObjectSerializer(BlueprintEntity),
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
Boolean,
|
||||
new CustomSerializer(
|
||||
/** @param {Boolean} boolean */
|
||||
(boolean, insideString) => boolean
|
||||
? insideString
|
||||
? "true"
|
||||
: "True"
|
||||
: insideString
|
||||
? "false"
|
||||
: "False",
|
||||
Boolean
|
||||
)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
ByteEntity,
|
||||
new ToStringSerializer(ByteEntity)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
ColorChannelEntity,
|
||||
new ToStringSerializer(ColorChannelEntity)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
EnumDisplayValueEntity,
|
||||
new ToStringSerializer(EnumDisplayValueEntity)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
EnumEntity,
|
||||
new ToStringSerializer(EnumEntity)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
FormatTextEntity,
|
||||
new CustomSerializer(
|
||||
(v, insideString) => {
|
||||
let result = v.getLookbehind() + "("
|
||||
+ v.value.map(v =>
|
||||
SerializerFactory.getSerializer(Utility.getType(v)).write(v, insideString)
|
||||
).join(", ")
|
||||
+ ")"
|
||||
return result
|
||||
},
|
||||
FormatTextEntity)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
FunctionReferenceEntity,
|
||||
new Serializer(FunctionReferenceEntity, Serializer.bracketsWrapped)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
GuidEntity,
|
||||
new ToStringSerializer(GuidEntity)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
IdentifierEntity,
|
||||
new ToStringSerializer(IdentifierEntity)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
Integer64Entity,
|
||||
new ToStringSerializer(Integer64Entity)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
IntegerEntity,
|
||||
new ToStringSerializer(IntegerEntity)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
InvariantTextEntity,
|
||||
new Serializer(InvariantTextEntity, (entity, v) => `${entity.getLookbehind()}(${v})`, ", ", false, "", () => "")
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
KeyBindingEntity,
|
||||
new Serializer(KeyBindingEntity, Serializer.bracketsWrapped)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
LinearColorEntity,
|
||||
new Serializer(LinearColorEntity, Serializer.bracketsWrapped)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
LocalizedTextEntity,
|
||||
new Serializer(LocalizedTextEntity, (entity, v) => `${entity.getLookbehind()}(${v})`, ", ", false, "", () => "")
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
MacroGraphReferenceEntity,
|
||||
new Serializer(MacroGraphReferenceEntity, Serializer.bracketsWrapped)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
MirroredEntity,
|
||||
new CustomSerializer(
|
||||
(v, insideString) => SerializerFactory.getSerializer(v.getTargetType()).write(v.get(), insideString),
|
||||
MirroredEntity
|
||||
)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
Number,
|
||||
new ToStringSerializer(Number)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
ObjectEntity,
|
||||
new ObjectSerializer()
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
ObjectReferenceEntity,
|
||||
new ToStringSerializer(ObjectReferenceEntity, false)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
PathSymbolEntity,
|
||||
new ToStringSerializer(PathSymbolEntity)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
PinEntity,
|
||||
new Serializer(PinEntity, (entity, v) => `${entity.getLookbehind()} (${v})`, ",", true)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
PinReferenceEntity,
|
||||
new Serializer(PinReferenceEntity, undefined, " ", false, "", () => "")
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
PinTypeEntity,
|
||||
new Serializer(PinTypeEntity)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
TerminalTypeEntity,
|
||||
new Serializer(TerminalTypeEntity, Serializer.bracketsWrapped)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
RBSerializationVector2DEntity,
|
||||
new CustomSerializer(
|
||||
(value, insideString) => `X=${value.X} Y=${value.Y}`,
|
||||
RBSerializationVector2DEntity
|
||||
)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
RotatorEntity,
|
||||
new Serializer(RotatorEntity, Serializer.bracketsWrapped)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
ScriptVariableEntity,
|
||||
new Serializer(ScriptVariableEntity, Serializer.bracketsWrapped)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
String,
|
||||
new CustomSerializer(
|
||||
(value, insideString) => insideString
|
||||
? Utility.escapeString(value)
|
||||
: `"${Utility.escapeString(value)}"`,
|
||||
String
|
||||
)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
SimpleSerializationRotatorEntity,
|
||||
new CustomSerializer(
|
||||
(value, insideString) => `${value.P}, ${value.Y}, ${value.R}`,
|
||||
SimpleSerializationRotatorEntity
|
||||
)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
SimpleSerializationVector2DEntity,
|
||||
new CustomSerializer(
|
||||
(value, insideString) => `${value.X}, ${value.Y}`,
|
||||
SimpleSerializationVector2DEntity
|
||||
)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
SimpleSerializationVectorEntity,
|
||||
new CustomSerializer(
|
||||
(value, insideString) => `${value.X}, ${value.Y}, ${value.Z}`,
|
||||
SimpleSerializationVectorEntity
|
||||
)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
SimpleSerializationVector4DEntity,
|
||||
new CustomSerializer(
|
||||
(value, insideString) => `${value.X}, ${value.Y}, ${value.Z}, ${value.W}`,
|
||||
SimpleSerializationVector4DEntity
|
||||
)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
SymbolEntity,
|
||||
new ToStringSerializer(SymbolEntity)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
UnknownKeysEntity,
|
||||
new Serializer(UnknownKeysEntity, (entity, string) => `${entity.getLookbehind() ?? ""}(${string})`)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
VariableReferenceEntity,
|
||||
new Serializer(VariableReferenceEntity, Serializer.bracketsWrapped)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
Vector2DEntity,
|
||||
new Serializer(Vector2DEntity, Serializer.bracketsWrapped)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
VectorEntity,
|
||||
new Serializer(VectorEntity, Serializer.bracketsWrapped)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
Vector4DEntity,
|
||||
new Serializer(Vector4DEntity, Serializer.bracketsWrapped)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export default class CommentNodeTemplate extends IResizeableTemplate {
|
||||
<div class="ueb-node-border">
|
||||
<div class="ueb-node-wrapper">
|
||||
<div class="ueb-node-top"
|
||||
.innerText="${Utility.encodeHTMLWhitespace(this.element.entity.NodeComment)}">
|
||||
.innerText="${Utility.encodeHTMLWhitespace(this.element.entity.NodeComment?.valueOf())}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -40,7 +40,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?.valueOf() === "delegate"),
|
||||
new MinimalPinTemplate(),
|
||||
this.element
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { html } from "lit"
|
||||
import Configuration from "../../Configuration.js"
|
||||
import StringEntity from "../../entity/StringEntity.js"
|
||||
import Utility from "../../Utility.js"
|
||||
import IInputPinTemplate from "./IInputPinTemplate.js"
|
||||
|
||||
@@ -15,11 +16,11 @@ export default class EnumPinTemplate extends IInputPinTemplate {
|
||||
|
||||
setup() {
|
||||
super.setup()
|
||||
const enumEntries = this.element.nodeElement.entity.EnumEntries
|
||||
const enumEntries = this.element.nodeElement.entity.EnumEntries.valueOf()
|
||||
this.#dropdownEntries =
|
||||
enumEntries?.map(k => {
|
||||
if (k === "") {
|
||||
k = "None"
|
||||
if (k.valueOf() === "") {
|
||||
k = new StringEntity("None")
|
||||
}
|
||||
return [
|
||||
k,
|
||||
|
||||
@@ -11,7 +11,7 @@ export default class ExecPinTemplate extends PinTemplate {
|
||||
renderName() {
|
||||
let pinName = this.element.entity.PinName
|
||||
if (this.element.entity.PinFriendlyName) {
|
||||
pinName = this.element.entity.PinFriendlyName.toString()
|
||||
pinName = this.element.entity.PinFriendlyName.valueOf()
|
||||
} else if (pinName === "execute" || pinName === "then") {
|
||||
return html``
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ export default class PinTemplate extends ITemplate {
|
||||
case "Set": return SVGIcon.setPin
|
||||
case "Map": return SVGIcon.mapPin
|
||||
}
|
||||
if (this.element.entity.PinType?.PinCategory?.toLocaleLowerCase() === "delegate") {
|
||||
if (this.element.entity.PinType?.PinCategory?.valueOf().toLocaleLowerCase() === "delegate") {
|
||||
return SVGIcon.delegate
|
||||
}
|
||||
if (this.element.nodeElement?.template instanceof VariableOperationNodeTemplate) {
|
||||
@@ -141,8 +141,8 @@ export default class PinTemplate extends ITemplate {
|
||||
|
||||
isInputRendered() {
|
||||
return this.element.isInput()
|
||||
&& !this.element.entity.bDefaultValueIsIgnored
|
||||
&& !this.element.entity.PinType.bIsReference
|
||||
&& !this.element.entity.bDefaultValueIsIgnored?.valueOf()
|
||||
&& !this.element.entity.PinType.bIsReference?.valueOf()
|
||||
}
|
||||
|
||||
renderInput() {
|
||||
@@ -170,6 +170,7 @@ export default class PinTemplate extends ITemplate {
|
||||
|
||||
getLinkLocation() {
|
||||
const rect = this.iconElement.getBoundingClientRect()
|
||||
/** @type {[Number, Number]} */
|
||||
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])
|
||||
|
||||
@@ -7,15 +7,15 @@ import INumericPinTemplate from "./INumericPinTemplate.js"
|
||||
export default class RotatorPinTemplate extends INumericPinTemplate {
|
||||
|
||||
#getR() {
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.R ?? 0)
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.R.valueOf() ?? 0)
|
||||
}
|
||||
|
||||
#getP() {
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.P ?? 0)
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.P.valueOf() ?? 0)
|
||||
}
|
||||
|
||||
#getY() {
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.Y ?? 0)
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.Y.valueOf() ?? 0)
|
||||
}
|
||||
|
||||
setDefaultValue(values = [], rawValues = values) {
|
||||
@@ -23,9 +23,9 @@ export default class RotatorPinTemplate extends INumericPinTemplate {
|
||||
if (!(rotator instanceof RotatorEntity)) {
|
||||
throw new TypeError("Expected DefaultValue to be a RotatorEntity")
|
||||
}
|
||||
rotator.R = values[0] // Roll
|
||||
rotator.P = values[1] // Pitch
|
||||
rotator.Y = values[2] // Yaw
|
||||
rotator.R.value = values[0] // Roll
|
||||
rotator.P.value = values[1] // Pitch
|
||||
rotator.Y.value = values[2] // Yaw
|
||||
this.element.requestUpdate("DefaultValue", rotator)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,11 +9,11 @@ import INumericPinTemplate from "./INumericPinTemplate.js"
|
||||
export default class Vector2DPinTemplate extends INumericPinTemplate {
|
||||
|
||||
#getX() {
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.X ?? 0)
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.X.valueOf() ?? 0)
|
||||
}
|
||||
|
||||
#getY() {
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.Y ?? 0)
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.Y.valueOf() ?? 0)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,8 +25,8 @@ export default class Vector2DPinTemplate extends INumericPinTemplate {
|
||||
if (!(vector instanceof Vector2DEntity)) {
|
||||
throw new TypeError("Expected DefaultValue to be a Vector2DEntity")
|
||||
}
|
||||
vector.X = values[0]
|
||||
vector.Y = values[1]
|
||||
vector.X.value = values[0]
|
||||
vector.Y.value = values[1]
|
||||
this.element.requestUpdate("DefaultValue", vector)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,19 +7,19 @@ import Vector4DEntity from "../../entity/Vector4DEntity.js"
|
||||
export default class Vector4DPinTemplate extends INumericPinTemplate {
|
||||
|
||||
#getX() {
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.X ?? 0)
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.X.valueOf() ?? 0)
|
||||
}
|
||||
|
||||
#getY() {
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.Y ?? 0)
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.Y.valueOf() ?? 0)
|
||||
}
|
||||
|
||||
#getZ() {
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.Z ?? 0)
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.Z.valueOf() ?? 0)
|
||||
}
|
||||
|
||||
#getW() {
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.W ?? 0)
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.W.valueOf() ?? 0)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,10 +31,10 @@ export default class Vector4DPinTemplate extends INumericPinTemplate {
|
||||
if (!(vector instanceof Vector4DEntity)) {
|
||||
throw new TypeError("Expected DefaultValue to be a Vector4DEntity")
|
||||
}
|
||||
vector.X = values[0]
|
||||
vector.Y = values[1]
|
||||
vector.Z = values[2]
|
||||
vector.W = values[3]
|
||||
vector.X.value = values[0]
|
||||
vector.Y.value = values[1]
|
||||
vector.Z.value = values[2]
|
||||
vector.W.value = values[3]
|
||||
this.element.requestUpdate("DefaultValue", vector)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,15 +7,15 @@ import INumericPinTemplate from "./INumericPinTemplate.js"
|
||||
export default class VectorPinTemplate extends INumericPinTemplate {
|
||||
|
||||
#getX() {
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.X ?? 0)
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.X.valueOf() ?? 0)
|
||||
}
|
||||
|
||||
#getY() {
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.Y ?? 0)
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.Y.valueOf() ?? 0)
|
||||
}
|
||||
|
||||
#getZ() {
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.Z ?? 0)
|
||||
return Utility.printNumber(this.element.getDefaultValue()?.Z.valueOf() ?? 0)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,9 +27,9 @@ export default class VectorPinTemplate extends INumericPinTemplate {
|
||||
if (!(vector instanceof VectorEntity)) {
|
||||
throw new TypeError("Expected DefaultValue to be a VectorEntity")
|
||||
}
|
||||
vector.X = values[0]
|
||||
vector.Y = values[1]
|
||||
vector.Z = values[2]
|
||||
vector.X.value = values[0]
|
||||
vector.Y.value = values[1]
|
||||
vector.Z.value = values[2]
|
||||
this.element.requestUpdate("DefaultValue", vector)
|
||||
}
|
||||
|
||||
|
||||
69
tests/customEntities.spec.js
Normal file
69
tests/customEntities.spec.js
Normal file
@@ -0,0 +1,69 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import StringEntity from "../js/entity/StringEntity.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 entity2Value from "./resources/serializedEntity2.js"
|
||||
import entity2Value1 from "./resources/serializedEntity2-1.js"
|
||||
import entity3Value from "./resources/serializedEntity3.js"
|
||||
import entity4Value from "./resources/serializedEntity4.js"
|
||||
|
||||
test.beforeAll(() => initializeSerializerFactory())
|
||||
|
||||
test.describe.configure({ mode: "parallel" })
|
||||
|
||||
test("Entity2", () => {
|
||||
const value = new Entity2()
|
||||
expect(Object.keys(value)).toHaveLength(9)
|
||||
expect(value.toString()).toEqual(entity2Value)
|
||||
const other = new Entity2({ someString2: new StringEntity("gamma") })
|
||||
expect(value.equals(other)).toBeFalsy()
|
||||
other.someString2 = new StringEntity("beta")
|
||||
expect(value.equals(other)).toBeTruthy()
|
||||
})
|
||||
|
||||
test("Entity2-1", () => {
|
||||
Entity2.attributes.someEntity = Entity2.attributes.someEntity.flagInlined()
|
||||
const value = new Entity2()
|
||||
expect(value.toString()).toEqual(entity2Value1)
|
||||
})
|
||||
|
||||
test("Entity3", () => {
|
||||
let value = new Entity3()
|
||||
const keys = [
|
||||
"alpha",
|
||||
"bravo",
|
||||
"charlie",
|
||||
"delta",
|
||||
"echo",
|
||||
"foxtrot",
|
||||
"golf",
|
||||
"hotel",
|
||||
"india",
|
||||
"juliett",
|
||||
"kilo",
|
||||
// "lima", // Not defined by default
|
||||
"mike",
|
||||
"november",
|
||||
"oscar",
|
||||
"papa",
|
||||
// "quebec", // Not defined by default
|
||||
"romeo",
|
||||
"sierra",
|
||||
]
|
||||
expect(Object.keys(value)).toStrictEqual(keys)
|
||||
expect(value.toString()).toEqual(entity3Value)
|
||||
})
|
||||
|
||||
test("Entity4", () => {
|
||||
Entity1.attributeSeparator = " - "
|
||||
Entity1.keySeparator = ":"
|
||||
Entity1.printKey = k => k.toUpperCase()
|
||||
Entity1.wrap = (entity, v) => `E1[${v}]`
|
||||
const entity = new Entity4()
|
||||
expect(entity.toString()).toEqual(entity4Value)
|
||||
})
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,581 +0,0 @@
|
||||
import { expect, test } from "@playwright/test"
|
||||
import Utility from "../js/Utility.js"
|
||||
import FormatTextEntity from "../js/entity/FormatTextEntity.js"
|
||||
import GuidEntity from "../js/entity/GuidEntity.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 PinEntity from "../js/entity/PinEntity.js"
|
||||
import RotatorEntity from "../js/entity/RotatorEntity.js"
|
||||
import SimpleSerializationRotatorEntity from "../js/entity/SimpleSerializationRotatorEntity.js"
|
||||
import SimpleSerializationVector2DEntity from "../js/entity/SimpleSerializationVector2DEntity.js"
|
||||
import SimpleSerializationVectorEntity from "../js/entity/SimpleSerializationVectorEntity.js"
|
||||
import SymbolEntity from "../js/entity/SymbolEntity.js"
|
||||
import UnknownKeysEntity from "../js/entity/UnknownKeysEntity.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"
|
||||
|
||||
test.beforeAll(() => initializeSerializerFactory())
|
||||
|
||||
test.describe.configure({ mode: "parallel" })
|
||||
|
||||
test("Array", () => {
|
||||
const serializer = SerializerFactory.getSerializer(Array)
|
||||
|
||||
expect(serializer.read("()")).toStrictEqual([])
|
||||
expect(serializer.read("( )")).toStrictEqual([])
|
||||
expect(serializer.read("(1, 2, 3, 4, 5, 6)")).toStrictEqual([1, 2, 3, 4, 5, 6])
|
||||
expect(serializer.read(`(
|
||||
"alpha",
|
||||
"beta",
|
||||
123,
|
||||
3BEF2168446CAA32D5B54289FAB2F0BA,
|
||||
Some(a=1, b="2")
|
||||
)`)).toStrictEqual([
|
||||
"alpha",
|
||||
"beta",
|
||||
123,
|
||||
new GuidEntity("3BEF2168446CAA32D5B54289FAB2F0BA"),
|
||||
new UnknownKeysEntity({
|
||||
lookbehind: "Some",
|
||||
a: 1,
|
||||
b: "2",
|
||||
})
|
||||
])
|
||||
expect(serializer.read(`(
|
||||
A(first = (9,8,7,6,5), second = 00000000000000000000000000000000),
|
||||
B(key="hello"),
|
||||
)`)).toStrictEqual([
|
||||
new UnknownKeysEntity({
|
||||
lookbehind: "A",
|
||||
first: [9, 8, 7, 6, 5],
|
||||
second: new GuidEntity("00000000000000000000000000000000"),
|
||||
}),
|
||||
new UnknownKeysEntity({
|
||||
lookbehind: "B",
|
||||
key: "hello",
|
||||
})
|
||||
])
|
||||
|
||||
// Nested
|
||||
expect(serializer.read("((1, 2), (3, 4))")).toStrictEqual([[1, 2], [3, 4]])
|
||||
expect(serializer.read('(((1, 2), (3, 4)), 5)')).toStrictEqual([[[1, 2], [3, 4]], 5])
|
||||
expect(serializer.read(`(
|
||||
One(a = (1,(2,(3,(4)))), b = ()),
|
||||
)`)).toStrictEqual([
|
||||
new UnknownKeysEntity({
|
||||
lookbehind: "One",
|
||||
a: [1, [2, [3, [4]]]],
|
||||
b: null,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
test("Boolean", () => {
|
||||
let serializer = SerializerFactory.getSerializer(Boolean)
|
||||
expect(serializer.read("true")).toStrictEqual(true)
|
||||
expect(serializer.read("True")).toStrictEqual(true)
|
||||
expect(serializer.read("false")).toStrictEqual(false)
|
||||
expect(serializer.read("False")).toStrictEqual(false)
|
||||
})
|
||||
|
||||
test("FormatTextEntity", () => {
|
||||
let serializer = SerializerFactory.getSerializer(FormatTextEntity)
|
||||
expect(
|
||||
serializer.read(`LOCGEN_FORMAT_NAMED(NSLOCTEXT("KismetSchema", "SplitPinFriendlyNameFormat", "{PinDisplayName} {ProtoPinDisplayName}"), "PinDisplayName", "Out Hit", "ProtoPinDisplayName", "Blocking Hit")`)
|
||||
.toString()
|
||||
).toBe("Out Hit Blocking Hit")
|
||||
expect(
|
||||
serializer.read(`LOCGEN_FORMAT_NAMED(NSLOCTEXT("KismetSchema", "SplitPinFriendlyNameFormat", "{PinDisplayName} {ProtoPinDisplayName}"), "PinDisplayName", "Out Hit", "ProtoPinDisplayName", "Hit Bone Name")`)
|
||||
.toString()
|
||||
).toBe("Out Hit Hit Bone Name")
|
||||
expect(
|
||||
serializer.read(String.raw`LOCGEN_FORMAT_ORDERED(
|
||||
NSLOCTEXT(
|
||||
"PCGSettings",
|
||||
"OverridableParamPinTooltip",
|
||||
"{0}Attribute type is \"{1}\" and its exact name is \"{2}\""
|
||||
),
|
||||
"If InRangeMin = InRangeMax, then that density value is mapped to the average of OutRangeMin and OutRangeMax\n",
|
||||
"float",
|
||||
"InRangeMin"
|
||||
)`)
|
||||
.toString()
|
||||
|
||||
).toBe(`If InRangeMin = InRangeMax, then that density value is mapped to the average of OutRangeMin and OutRangeMax\nAttribute type is "float" and its exact name is "InRangeMin"`)
|
||||
})
|
||||
|
||||
test("GuidEntity", () => {
|
||||
let serializer = SerializerFactory.getSerializer(GuidEntity)
|
||||
|
||||
let guid = serializer.read("0556a3ecabf648d0a5c07b2478e9dd32")
|
||||
expect(guid).toBeInstanceOf(GuidEntity)
|
||||
expect(guid.value).toBe("0556a3ecabf648d0a5c07b2478e9dd32")
|
||||
|
||||
guid = serializer.read("64023BC344E0453DBB583FAC411489BC")
|
||||
expect(guid).toBeInstanceOf(GuidEntity)
|
||||
expect(guid.value).toBe("64023BC344E0453DBB583FAC411489BC")
|
||||
|
||||
guid = serializer.read("6edC4a425ca948da8bC78bA52DED6C6C")
|
||||
expect(guid).toBeInstanceOf(GuidEntity)
|
||||
expect(guid.value).toBe("6edC4a425ca948da8bC78bA52DED6C6C")
|
||||
|
||||
expect(() => serializer.read("172087193 9B04362973544B3564FDB2C")).toThrow()
|
||||
expect(() => serializer.read("E25F14F8F3E9441AB07153E7DA2BA2B")).toThrow()
|
||||
expect(() => serializer.read("A78988B0097E48418C8CB87EC5A67ABF7")).toThrow()
|
||||
})
|
||||
|
||||
test("IntegerEntity", () => {
|
||||
let serializer = SerializerFactory.getSerializer(IntegerEntity)
|
||||
|
||||
let integer = serializer.read("0")
|
||||
expect(integer).toBeInstanceOf(IntegerEntity)
|
||||
expect(integer.value).toStrictEqual(0)
|
||||
|
||||
integer = serializer.read("+0")
|
||||
expect(integer).toBeInstanceOf(IntegerEntity)
|
||||
expect(integer.value).toStrictEqual(0)
|
||||
|
||||
integer = serializer.read("-0")
|
||||
expect(integer).toBeInstanceOf(IntegerEntity)
|
||||
expect(integer.value).toStrictEqual(0)
|
||||
|
||||
integer = serializer.read("99")
|
||||
expect(integer).toBeInstanceOf(IntegerEntity)
|
||||
expect(integer.value).toStrictEqual(99)
|
||||
|
||||
integer = serializer.read("-8685")
|
||||
expect(integer).toBeInstanceOf(IntegerEntity)
|
||||
expect(integer.value).toStrictEqual(-8685)
|
||||
|
||||
integer = serializer.read("+555")
|
||||
expect(integer).toBeInstanceOf(IntegerEntity)
|
||||
expect(integer.value).toStrictEqual(555)
|
||||
|
||||
integer = serializer.read("1000000000")
|
||||
expect(integer).toBeInstanceOf(IntegerEntity)
|
||||
expect(integer.value).toStrictEqual(1000000000)
|
||||
|
||||
expect(() => serializer.read("1.2").value).toThrow()
|
||||
})
|
||||
|
||||
test("KeyBindingEntity", () => {
|
||||
let serializer = SerializerFactory.getSerializer(KeyBindingEntity)
|
||||
|
||||
let binding = serializer.read("A")
|
||||
expect(binding).toBeInstanceOf(KeyBindingEntity)
|
||||
expect(binding).toMatchObject({ Key: { value: "A" } })
|
||||
|
||||
binding = serializer.read("(bCtrl=True,Key=A)")
|
||||
expect(binding).toBeInstanceOf(KeyBindingEntity)
|
||||
expect(binding).toMatchObject({ Key: { value: "A" }, bCtrl: true })
|
||||
|
||||
binding = serializer.read("(bCtrl=false,bShift=false,bCmd=true,bAlt=false,Key=X)")
|
||||
expect(binding).toBeInstanceOf(KeyBindingEntity)
|
||||
expect(binding).toMatchObject({ Key: { value: "X" }, bAlt: false, bCtrl: false, bCmd: true })
|
||||
|
||||
binding = serializer.read("( bCtrl= false \n, Key \n\n\n =Y ,bAlt=true )")
|
||||
expect(binding).toBeInstanceOf(KeyBindingEntity)
|
||||
expect(binding).toMatchObject({ Key: { value: "Y" }, bAlt: true, bCtrl: false })
|
||||
})
|
||||
|
||||
test("LinearColorEntity", () => {
|
||||
const serializer = SerializerFactory.getSerializer(LinearColorEntity)
|
||||
|
||||
let color = LinearColorEntity.getWhite()
|
||||
expect(color.toRGBA()).toStrictEqual([255, 255, 255, 255])
|
||||
expect(color.toRGBAString()).toStrictEqual("FFFFFFFF")
|
||||
expect(color.toNumber()).toStrictEqual(-1)
|
||||
expect(color.toHSVA()).toStrictEqual([0, 0, 1, 1])
|
||||
|
||||
color = serializer.read("(R=1,G=0,B=0)")
|
||||
expect(color.toRGBA()).toStrictEqual([255, 0, 0, 255])
|
||||
expect(color.toRGBAString()).toStrictEqual("FF0000FF")
|
||||
expect(color.toNumber()).toStrictEqual(-16776961)
|
||||
expect(color.toHSVA()).toStrictEqual([0, 1, 1, 1])
|
||||
|
||||
color = serializer.read("(R=0.000000,G=0.660000,B=1.000000,A=1.000000)")
|
||||
expect(color.toRGBA()).toStrictEqual([0, 168, 255, 255])
|
||||
expect(color.toRGBAString()).toStrictEqual("00A8FFFF")
|
||||
expect(color.toNumber()).toStrictEqual(11075583)
|
||||
expect(color.toHSVA()).toStrictEqual([0.55666666666666666666, 1, 1, 1])
|
||||
|
||||
color = serializer.read("(B=0.04394509003266556,G=0.026789300067696642,A=0.83663232408635,R=0.6884158028074934,)")
|
||||
expect(color.toRGBA()).toStrictEqual([176, 7, 11, 213])
|
||||
expect(color.toRGBAString()).toStrictEqual("B0070BD5")
|
||||
expect(color.toNumber()).toStrictEqual(-1341715499)
|
||||
expect(color.toHSVA().map(v => Utility.roundDecimals(v, 3))).toStrictEqual([0.996, 0.961, 0.688, 0.837])
|
||||
|
||||
color = serializer.read(`(
|
||||
A = 0.327 ,
|
||||
R=0.530 , G = 0.685
|
||||
,B
|
||||
= 0.9 ,)`)
|
||||
expect(color.toRGBA()).toStrictEqual([135, 175, 230, 83])
|
||||
expect(color.toRGBAString()).toStrictEqual("87AFE653")
|
||||
expect(color.toNumber()).toStrictEqual(-2018515373)
|
||||
expect(color.toHSVA().map(v => Utility.roundDecimals(v, 3))).toStrictEqual([0.597, 0.411, 0.9, 0.327])
|
||||
|
||||
expect(() => serializer.read("(R=0.000000,G=0.660000,A=1.000000)")).toThrow()
|
||||
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)
|
||||
|
||||
expect(serializer.read("0")).toBeCloseTo(0, 0.00001)
|
||||
expect(serializer.read("+0")).toBeCloseTo(0, 0.00001)
|
||||
expect(serializer.read("-0")).toBeCloseTo(0, 0.00001)
|
||||
expect(serializer.read("5")).toBeCloseTo(5, 0.00001)
|
||||
expect(serializer.read("0.05")).toBeCloseTo(0.05, 0.00001)
|
||||
expect(serializer.read("-999.666")).toBeCloseTo(-999.666, 0.001)
|
||||
expect(serializer.read("+45.4545")).toBeCloseTo(45.4545, 0.001)
|
||||
expect(serializer.read("+1000000000")).toBeCloseTo(1E9, 0.1)
|
||||
expect(serializer.read("inf")).toBe(Number.POSITIVE_INFINITY)
|
||||
expect(serializer.read("+inf")).toBe(Number.POSITIVE_INFINITY)
|
||||
expect(serializer.read("-inf")).toBe(Number.NEGATIVE_INFINITY)
|
||||
expect(() => serializer.read("alpha")).toThrow()
|
||||
})
|
||||
|
||||
test("ObjectReferenceEntity", () => {
|
||||
const serializer = SerializerFactory.getSerializer(ObjectReferenceEntity)
|
||||
|
||||
let reference = serializer.read("Class")
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({ type: "Class", path: "" })
|
||||
expect(serializer.write(reference)).toBe("Class")
|
||||
|
||||
reference = serializer.read(`Class'/Script/ShooterGame.ShooterGameMode'`)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({ type: "Class", path: "/Script/ShooterGame.ShooterGameMode" })
|
||||
expect(serializer.write(reference)).toBe(`Class'/Script/ShooterGame.ShooterGameMode'`)
|
||||
|
||||
reference = serializer.read(`EdGraphPin'EdGraphPin_45417'`)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({ type: "EdGraphPin", path: "EdGraphPin_45417" })
|
||||
expect(serializer.write(reference)).toBe(`EdGraphPin'EdGraphPin_45417'`)
|
||||
|
||||
reference = serializer.read(`EdGraphPin'"K2Node_DynamicCast_2126.EdGraphPin_3990988"'`)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({ type: "EdGraphPin", path: "K2Node_DynamicCast_2126.EdGraphPin_3990988" })
|
||||
expect(serializer.write(reference)).toBe(`EdGraphPin'"K2Node_DynamicCast_2126.EdGraphPin_3990988"'`)
|
||||
|
||||
reference = serializer.read(
|
||||
`"/Script/Engine.MaterialExpressionMaterialFunctionCall'MaterialExpressionMaterialFunctionCall_0'"`
|
||||
)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({
|
||||
type: "/Script/Engine.MaterialExpressionMaterialFunctionCall",
|
||||
path: "MaterialExpressionMaterialFunctionCall_0",
|
||||
})
|
||||
expect(serializer.write(reference)).toBe(
|
||||
`"/Script/Engine.MaterialExpressionMaterialFunctionCall'MaterialExpressionMaterialFunctionCall_0'"`
|
||||
)
|
||||
|
||||
reference = serializer.read(
|
||||
`/Script/Engine.EdGraph'"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:Do N"'`
|
||||
)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({
|
||||
type: "/Script/Engine.EdGraph",
|
||||
path: "/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:Do N",
|
||||
})
|
||||
expect(serializer.write(reference)).toBe(
|
||||
`/Script/Engine.EdGraph'"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:Do N"'`
|
||||
)
|
||||
|
||||
reference = serializer.read(
|
||||
`EdGraphPin'"K2Node_CommutativeAssociativeBinaryOperator_152.EdGraphPin_4045"'`
|
||||
)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({
|
||||
type: "EdGraphPin",
|
||||
path: "K2Node_CommutativeAssociativeBinaryOperator_152.EdGraphPin_4045",
|
||||
})
|
||||
expect(serializer.write(reference)).toBe(
|
||||
`EdGraphPin'"K2Node_CommutativeAssociativeBinaryOperator_152.EdGraphPin_4045"'`
|
||||
)
|
||||
|
||||
reference = serializer.read(
|
||||
`Function'"/Game/Mods/CrazyDinos/ElementalDragon/CDElementalDragon_Character_BP.SKEL_CDElementalDragon_Character_BP_C:ROS Change Element"'`
|
||||
)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({
|
||||
type: "Function",
|
||||
path: "/Game/Mods/CrazyDinos/ElementalDragon/CDElementalDragon_Character_BP.SKEL_CDElementalDragon_Character_BP_C:ROS Change Element",
|
||||
})
|
||||
expect(serializer.write(reference)).toBe(
|
||||
`Function'"/Game/Mods/CrazyDinos/ElementalDragon/CDElementalDragon_Character_BP.SKEL_CDElementalDragon_Character_BP_C:ROS Change Element"'`
|
||||
)
|
||||
|
||||
reference = serializer.read(`EdGraph'/Game/Systems/BP_MacroGlobal.BP_MacroGlobal:Or+Branch'`)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({
|
||||
type: "EdGraph",
|
||||
path: "/Game/Systems/BP_MacroGlobal.BP_MacroGlobal:Or+Branch",
|
||||
})
|
||||
expect(serializer.write(reference)).toBe(`EdGraph'/Game/Systems/BP_MacroGlobal.BP_MacroGlobal:Or+Branch'`)
|
||||
|
||||
reference = serializer.read(`/Script/Engine.EdGraph'"+-Weird/2,Macro"'`)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({ type: "/Script/Engine.EdGraph", path: "+-Weird/2,Macro" })
|
||||
expect(serializer.write(reference)).toBe(`/Script/Engine.EdGraph'"+-Weird/2,Macro"'`)
|
||||
|
||||
reference = serializer.read(`/Script/BlueprintGraph.K2Node_VariableGet`)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({ type: "/Script/BlueprintGraph.K2Node_VariableGet", path: "" })
|
||||
expect(serializer.write(reference)).toBe(`/Script/BlueprintGraph.K2Node_VariableGet`)
|
||||
|
||||
reference = serializer.read(
|
||||
`/Script/Engine.MaterialExpressionMaterialFunctionCall'MaterialExpressionMaterialFunctionCall_0'`
|
||||
)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({
|
||||
type: "/Script/Engine.MaterialExpressionMaterialFunctionCall",
|
||||
path: "MaterialExpressionMaterialFunctionCall_0",
|
||||
})
|
||||
expect(serializer.write(reference)).toBe(
|
||||
`/Script/Engine.MaterialExpressionMaterialFunctionCall'MaterialExpressionMaterialFunctionCall_0'`
|
||||
)
|
||||
|
||||
reference = serializer.read(
|
||||
`/Script/Engine.MaterialExpressionMaterialFunctionCall'/Engine/Transient.Material_0:MaterialGraph_0.MaterialGraphNode_3.MaterialExpressionMaterialFunctionCall_0'`
|
||||
)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({
|
||||
type: "/Script/Engine.MaterialExpressionMaterialFunctionCall",
|
||||
path: "/Engine/Transient.Material_0:MaterialGraph_0.MaterialGraphNode_3.MaterialExpressionMaterialFunctionCall_0",
|
||||
})
|
||||
expect(serializer.write(reference)).toBe(
|
||||
`/Script/Engine.MaterialExpressionMaterialFunctionCall'/Engine/Transient.Material_0:MaterialGraph_0.MaterialGraphNode_3.MaterialExpressionMaterialFunctionCall_0'`
|
||||
)
|
||||
|
||||
reference = serializer.read(`/Script/CoreUObject.Class'"/Script/Engine.GameModeBase"'`)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({
|
||||
type: "/Script/CoreUObject.Class",
|
||||
path: "/Script/Engine.GameModeBase",
|
||||
})
|
||||
expect(serializer.write(reference)).toBe(`/Script/CoreUObject.Class'"/Script/Engine.GameModeBase"'`)
|
||||
|
||||
reference = serializer.read(`"/Game/_YukiritoLib/Textures/T_紫色渐变01.T_紫色渐变01"`)
|
||||
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
|
||||
expect(reference).toMatchObject({
|
||||
type: "/Game/_YukiritoLib/Textures/T_紫色渐变01.T_紫色渐变01",
|
||||
path: "",
|
||||
})
|
||||
})
|
||||
|
||||
test("PinEntity", () => {
|
||||
const serializer = SerializerFactory.getSerializer(PinEntity)
|
||||
|
||||
expect(serializer.read("Pin (PinType.PinSubCategoryMemberReference=())")).toMatchObject({
|
||||
"PinType": { "PinSubCategoryMemberReference": null }
|
||||
})
|
||||
})
|
||||
|
||||
test("SimpleSerializationRotatorEntity", () => {
|
||||
const serializer = SerializerFactory.getSerializer(SimpleSerializationRotatorEntity)
|
||||
|
||||
expect(serializer.read("0, 0, 0")).toEqual(new SimpleSerializationRotatorEntity({
|
||||
R: 0,
|
||||
P: 0,
|
||||
Y: 0,
|
||||
}))
|
||||
expect(serializer.read("0.65, 1.0, 0.99")).toEqual(new SimpleSerializationRotatorEntity({
|
||||
P: 0.65,
|
||||
Y: 1.0,
|
||||
R: 0.99,
|
||||
}))
|
||||
expect(serializer.read("7,6,5")).toEqual(new SimpleSerializationRotatorEntity({
|
||||
P: 7,
|
||||
Y: 6,
|
||||
R: 5,
|
||||
}))
|
||||
})
|
||||
|
||||
test("SimpleSerializationVector2DEntity", () => {
|
||||
const serializer = SerializerFactory.getSerializer(SimpleSerializationVector2DEntity)
|
||||
|
||||
expect(serializer.read("0, 0")).toEqual(new SimpleSerializationVector2DEntity({
|
||||
X: 0,
|
||||
Y: 0,
|
||||
}))
|
||||
expect(serializer.read("127.8, 13.3")).toEqual(new SimpleSerializationVector2DEntity({
|
||||
X: 127.8,
|
||||
Y: 13.3,
|
||||
}))
|
||||
expect(serializer.read("5,0")).toEqual(new SimpleSerializationVector2DEntity({
|
||||
X: 5,
|
||||
Y: 0,
|
||||
}))
|
||||
})
|
||||
|
||||
test("SimpleSerializationVectorEntity", () => {
|
||||
const serializer = SerializerFactory.getSerializer(SimpleSerializationVectorEntity)
|
||||
|
||||
expect(serializer.read("0, 0, 0")).toEqual(new SimpleSerializationVectorEntity({
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Z: 0,
|
||||
}))
|
||||
expect(serializer.read("1001, 56.4, 0.5")).toEqual(new SimpleSerializationVectorEntity({
|
||||
X: 1001,
|
||||
Y: 56.4,
|
||||
Z: 0.5,
|
||||
}))
|
||||
expect(serializer.read("-1,-2,-3")).toEqual(new SimpleSerializationVectorEntity({
|
||||
X: -1,
|
||||
Y: -2,
|
||||
Z: -3,
|
||||
}))
|
||||
})
|
||||
|
||||
test("String", () => {
|
||||
const serializer = SerializerFactory.getSerializer(String)
|
||||
|
||||
expect(serializer.read('""')).toStrictEqual("")
|
||||
expect(serializer.read('"hello"')).toStrictEqual("hello")
|
||||
expect(serializer.read('"hello world 123 - éèàò@ç ^ ^^^"')).toStrictEqual("hello world 123 - éèàò@ç ^ ^^^")
|
||||
expect(serializer.read('"\\""')).toStrictEqual('"')
|
||||
expect(() => serializer.read("Hello")).toThrow()
|
||||
|
||||
expect(serializer.write(`"/Script/CoreUObject.Class'/Script/Interhaptics.HapticSource'"`))
|
||||
.toBe(String.raw`"\"/Script/CoreUObject.Class'/Script/Interhaptics.HapticSource'\""`)
|
||||
})
|
||||
|
||||
test("UnknownKeysValue", () => {
|
||||
const parser = Grammar.unknownValue
|
||||
|
||||
expect(parser.parse('"Hello"').constructor).toStrictEqual(String)
|
||||
expect(parser.parse("()")).toBeNull()
|
||||
expect(parser.parse("8345").constructor).toStrictEqual(Number)
|
||||
expect(parser.parse("True").constructor).toStrictEqual(Boolean)
|
||||
expect(parser.parse("False").constructor).toStrictEqual(Boolean)
|
||||
expect(parser.parse("F0223D3742E67C0D9FEFB2A64946B7F0").constructor).toStrictEqual(GuidEntity)
|
||||
expect(parser.parse("SYMBOL1").constructor).toStrictEqual(SymbolEntity)
|
||||
expect(parser.parse("Symbol_2_3_4").constructor).toStrictEqual(SymbolEntity)
|
||||
expect(parser.parse("(X=-0.495, Y=0, )").constructor).toStrictEqual(Vector2DEntity)
|
||||
expect(parser.parse("(X=-0.495,Y=+765.0,Z=7)").constructor).toStrictEqual(VectorEntity)
|
||||
expect(parser.parse("(R=1.000000,P=7.6,Y=+88.99)").constructor).toStrictEqual(RotatorEntity)
|
||||
expect(parser.parse("(R=0.000000,G=0.660000,B=1.000000,A=1.000000)").constructor)
|
||||
.toStrictEqual(LinearColorEntity)
|
||||
expect(parser.parse(`Class'"/Script/Engine.KismetSystemLibrary"'`).constructor)
|
||||
.toStrictEqual(ObjectReferenceEntity)
|
||||
expect(parser.parse("(1,2,3,4,5,6,7,8,9)")).toStrictEqual([1, 2, 3, 4, 5, 6, 7, 8, 9])
|
||||
expect(parser.parse(`( "Hello", "World", )`)).toStrictEqual(["Hello", "World"])
|
||||
expect(parser.parse(`( "Alpha", 123, Beta, "Gamma", "Delta", 99 )`))
|
||||
.toStrictEqual(["Alpha", 123, new SymbolEntity({ value: "Beta" }), "Gamma", "Delta", 99])
|
||||
})
|
||||
|
||||
test("UnknownKeysEntity", () => {
|
||||
const serializer = SerializerFactory.getSerializer(UnknownKeysEntity)
|
||||
|
||||
let unknown = serializer.read('LookbehindValue(FirstKey=1,SecondKey=SOME_SYMBOL2,ThirdKey="Hello")')
|
||||
expect(unknown).toBeInstanceOf(UnknownKeysEntity)
|
||||
expect(unknown).toMatchObject({
|
||||
lookbehind: "LookbehindValue",
|
||||
FirstKey: 1,
|
||||
SecondKey: new SymbolEntity("SOME_SYMBOL2"),
|
||||
ThirdKey: "Hello",
|
||||
})
|
||||
|
||||
unknown = serializer.read('(A = (-1,-2,-3), B = SomeFunction(B1 = "b1", B2 = (X=101,Y=102,Z=103)))')
|
||||
expect(unknown).toBeInstanceOf(UnknownKeysEntity)
|
||||
expect(unknown).toMatchObject({
|
||||
A: [-1, -2, -3],
|
||||
B: new UnknownKeysEntity({
|
||||
lookbehind: "SomeFunction",
|
||||
B1: "b1",
|
||||
B2: new VectorEntity({ X: 101, Y: 102, Z: 103 }),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
test("VectorEntity", () => {
|
||||
const serializer = SerializerFactory.getSerializer(VectorEntity)
|
||||
|
||||
let vector = serializer.read("(X=1,Y=2,Z=3.5)")
|
||||
expect(vector).toBeInstanceOf(VectorEntity)
|
||||
expect(vector).toStrictEqual(new VectorEntity({
|
||||
X: 1,
|
||||
Y: 2,
|
||||
Z: 3.5,
|
||||
}))
|
||||
|
||||
vector = serializer.read("(X=10,Y=+20.88,Z=-30.54,)")
|
||||
expect(vector).toBeInstanceOf(VectorEntity)
|
||||
expect(vector).toStrictEqual(new VectorEntity({
|
||||
X: 10,
|
||||
Y: 20.88,
|
||||
Z: -30.54,
|
||||
}))
|
||||
|
||||
vector = serializer.read(`(
|
||||
Z = -3.66 ,
|
||||
|
||||
X
|
||||
= -1 , Y =
|
||||
|
||||
|
||||
-2
|
||||
,
|
||||
)`)
|
||||
expect(vector).toBeInstanceOf(VectorEntity)
|
||||
expect(vector).toStrictEqual(new VectorEntity({
|
||||
X: -1,
|
||||
Y: -2,
|
||||
Z: -3.66,
|
||||
}))
|
||||
|
||||
expect(() => serializer.read("(X=1,Y=\"2\",Z=3)")).toThrow()
|
||||
expect(() => serializer.read("(X=1,Z=3)")).toThrow()
|
||||
expect(() => serializer.read("(X=1,Y=2,Unexpected=6,Z=3.5)")).toThrow()
|
||||
})
|
||||
|
||||
test("Vector2DEntity", () => {
|
||||
let serializer = SerializerFactory.getSerializer(Vector2DEntity)
|
||||
|
||||
let vector = serializer.read("(X=78,Y=56.3)")
|
||||
expect(vector).toBeInstanceOf(Vector2DEntity)
|
||||
expect(vector).toStrictEqual(new Vector2DEntity({
|
||||
X: 78,
|
||||
Y: 56.3,
|
||||
}))
|
||||
|
||||
vector = serializer.read("(X=+4.5,Y=-8.88,)")
|
||||
expect(vector).toBeInstanceOf(Vector2DEntity)
|
||||
expect(vector).toStrictEqual(new Vector2DEntity({
|
||||
X: 4.5,
|
||||
Y: -8.88,
|
||||
}))
|
||||
|
||||
vector = serializer.read(`(
|
||||
Y = +93.004 ,
|
||||
|
||||
X
|
||||
= 0 ,
|
||||
)`)
|
||||
expect(vector).toBeInstanceOf(Vector2DEntity)
|
||||
expect(vector).toStrictEqual(new Vector2DEntity({
|
||||
X: 0,
|
||||
Y: 93.004,
|
||||
}))
|
||||
|
||||
expect(() => serializer.read("(X=1,Y=\"2\")")).toThrow()
|
||||
expect(() => serializer.read("(X=1)")).toThrow()
|
||||
expect(() => serializer.read("(X=777, Y=555, Unexpected=6, HH=2)")).toThrow()
|
||||
})
|
||||
@@ -1,20 +1,13 @@
|
||||
import AttributeInfo from "../../js/entity/AttributeInfo.js"
|
||||
import IEntity from "../../js/entity/IEntity.js"
|
||||
import NumberEntity from "../../js/entity/NumberEntity.js"
|
||||
|
||||
export default class Entity1 extends IEntity {
|
||||
|
||||
static attributeSeparator = ", "
|
||||
static wrap = (entity, v) => `Entity1(${v})`
|
||||
static attributes = {
|
||||
a: new AttributeInfo({
|
||||
type: Number,
|
||||
default: 8,
|
||||
}),
|
||||
b: new AttributeInfo({
|
||||
type: Number,
|
||||
default: 9,
|
||||
}),
|
||||
}
|
||||
|
||||
constructor(values = {}) {
|
||||
super(values)
|
||||
...super.attributes,
|
||||
a: NumberEntity.withDefault(type => new type(8)),
|
||||
b: NumberEntity.withDefault(type => new type(9)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,38 @@
|
||||
import AttributeInfo from "../../js/entity/AttributeInfo.js"
|
||||
import ArrayEntity from "../../js/entity/ArrayEntity.js"
|
||||
import BooleanEntity from "../../js/entity/BooleanEntity.js"
|
||||
import IEntity from "../../js/entity/IEntity.js"
|
||||
import NumberEntity from "../../js/entity/NumberEntity.js"
|
||||
import StringEntity from "../../js/entity/StringEntity.js"
|
||||
import Entity1 from "./Entity1.js"
|
||||
|
||||
export default class Entity2 extends IEntity {
|
||||
|
||||
static attributeSeparator = "\n"
|
||||
static keySeparator = ": "
|
||||
static printKey = k => ` ${k}`
|
||||
static wrap = (entity, v) => `{\n${v}\n}`
|
||||
static attributes = {
|
||||
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()
|
||||
}),
|
||||
...super.attributes,
|
||||
someNumber: NumberEntity.withDefault(type => new type(567)),
|
||||
someString: StringEntity.withDefault(type => new type("alpha")),
|
||||
someString2: StringEntity.withDefault(type => new type("beta")),
|
||||
someBoolean: BooleanEntity.withDefault(type => new type(true)),
|
||||
someBoolean2: BooleanEntity.withDefault(),
|
||||
someObjectString: StringEntity.withDefault(type => new type("gamma")),
|
||||
someArray: ArrayEntity.of(NumberEntity).withDefault(type => new type([
|
||||
new NumberEntity(400),
|
||||
new NumberEntity(500),
|
||||
new NumberEntity(600),
|
||||
new NumberEntity(700),
|
||||
new NumberEntity(800),
|
||||
])),
|
||||
someArray2: ArrayEntity.of(NumberEntity).withDefault(type => new type([
|
||||
new NumberEntity(-400),
|
||||
new NumberEntity(-500),
|
||||
new NumberEntity(-600),
|
||||
new NumberEntity(-700),
|
||||
new NumberEntity(-800),
|
||||
])),
|
||||
someEntity: Entity1.withDefault(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,74 +1,58 @@
|
||||
import AttributeInfo from "../../js/entity/AttributeInfo.js"
|
||||
import AlternativesEntity from "../../js/entity/AlternativesEntity.js"
|
||||
import ArrayEntity from "../../js/entity/ArrayEntity.js"
|
||||
import BooleanEntity from "../../js/entity/BooleanEntity.js"
|
||||
import IEntity from "../../js/entity/IEntity.js"
|
||||
import Union from "../../js/entity/Union.js"
|
||||
import NullEntity from "../../js/entity/NullEntity.js"
|
||||
import NumberEntity from "../../js/entity/NumberEntity.js"
|
||||
import StringEntity from "../../js/entity/StringEntity.js"
|
||||
import Entity1 from "./Entity1.js"
|
||||
import Entity2 from "./Entity2.js"
|
||||
|
||||
export default class Entity3 extends IEntity {
|
||||
|
||||
static attributeSeparator = "\n"
|
||||
static keySeparator = ": "
|
||||
static printKey = k => ` ${k}`
|
||||
static wrap = (entity, v) => `[[\n${v}\n]]`
|
||||
static attributes = {
|
||||
alpha: AttributeInfo.createValue(32),
|
||||
bravo: new AttributeInfo({
|
||||
type: Number,
|
||||
default: 78,
|
||||
}),
|
||||
charlie: new AttributeInfo({
|
||||
type: String,
|
||||
default: "Charlie",
|
||||
}),
|
||||
delta: new AttributeInfo({
|
||||
type: String,
|
||||
default: null,
|
||||
}),
|
||||
echo: AttributeInfo.createValue("echo"),
|
||||
foxtrot: AttributeInfo.createValue(false),
|
||||
golf: AttributeInfo.createValue([]),
|
||||
hotel: new AttributeInfo({
|
||||
type: Array,
|
||||
default: null,
|
||||
}),
|
||||
india: new AttributeInfo({
|
||||
type: [Number],
|
||||
default: () => [],
|
||||
}),
|
||||
juliett: new AttributeInfo({
|
||||
type: [String],
|
||||
default: ["a", "b", "c", "d", "e"],
|
||||
}),
|
||||
kilo: new AttributeInfo({
|
||||
type: [Boolean],
|
||||
default: () => [true, false, false, true, true],
|
||||
}),
|
||||
lima: AttributeInfo.createType(String),
|
||||
mike: new AttributeInfo({
|
||||
type: new Union(Number, String, Array),
|
||||
default: "Bar",
|
||||
}),
|
||||
november: new AttributeInfo({
|
||||
type: new Union(Number, String, Array),
|
||||
default: 0,
|
||||
}),
|
||||
oscar: new AttributeInfo({
|
||||
type: Entity1,
|
||||
default: () => new Entity1()
|
||||
}),
|
||||
papa: new AttributeInfo({
|
||||
type: Entity1,
|
||||
default: () => new Entity1({ a: 12, b: 13 }),
|
||||
}),
|
||||
quebec: new AttributeInfo({
|
||||
default: 0, // will assign undefined because it does not satisfy the predicate
|
||||
predicate: v => v >= 1 && v <= 10,
|
||||
}),
|
||||
romeo: new AttributeInfo({
|
||||
type: Entity1,
|
||||
default: new Entity1(),
|
||||
inlined: true,
|
||||
}),
|
||||
sierra: new AttributeInfo({
|
||||
type: Entity2,
|
||||
default: new Entity2(),
|
||||
inlined: true,
|
||||
}),
|
||||
...super.attributes,
|
||||
alpha: NumberEntity.withDefault(type => new type(32)),
|
||||
bravo: NumberEntity.withDefault(type => new type(78)),
|
||||
charlie: StringEntity.withDefault(type => new type("Charlie")),
|
||||
delta: StringEntity.withDefault(type => new NullEntity()),
|
||||
echo: StringEntity.withDefault(type => new type("echo")),
|
||||
foxtrot: BooleanEntity.withDefault(),
|
||||
golf: ArrayEntity.of(StringEntity).withDefault(),
|
||||
hotel: ArrayEntity.of(NumberEntity).withDefault(() => new NullEntity()),
|
||||
india: ArrayEntity.of(NumberEntity).withDefault(),
|
||||
juliett: ArrayEntity.of(StringEntity).withDefault(type => new type([
|
||||
new StringEntity("a"),
|
||||
new StringEntity("b"),
|
||||
new StringEntity("c"),
|
||||
new StringEntity("d"),
|
||||
new StringEntity("e"),
|
||||
])),
|
||||
kilo: ArrayEntity.of(BooleanEntity).withDefault(type => new type([
|
||||
new BooleanEntity(true),
|
||||
new BooleanEntity(),
|
||||
new BooleanEntity(),
|
||||
new BooleanEntity(true),
|
||||
new BooleanEntity(true),
|
||||
])),
|
||||
lima: StringEntity,
|
||||
mike: AlternativesEntity
|
||||
.accepting(NumberEntity, StringEntity, ArrayEntity)
|
||||
.withDefault(type => new StringEntity("Bar")),
|
||||
november: AlternativesEntity
|
||||
.accepting(NumberEntity, StringEntity, ArrayEntity)
|
||||
.withDefault(type => new NumberEntity(0)),
|
||||
oscar: Entity1.withDefault(),
|
||||
papa: Entity1.withDefault(type => new type({
|
||||
a: new NumberEntity(12),
|
||||
b: new NumberEntity(13),
|
||||
})),
|
||||
quebec: NumberEntity,
|
||||
romeo: Entity1.withDefault().flagInlined(),
|
||||
sierra: Entity2.withDefault().flagInlined(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,23 @@
|
||||
import AttributeInfo from "../../js/entity/AttributeInfo.js"
|
||||
import ArrayEntity from "../../js/entity/ArrayEntity.js"
|
||||
import IEntity from "../../js/entity/IEntity.js"
|
||||
import NullEntity from "../../js/entity/NullEntity.js"
|
||||
import NumberEntity from "../../js/entity/NumberEntity.js"
|
||||
import Entity1 from "./Entity1.js"
|
||||
import Entity3 from "./Entity3.js"
|
||||
|
||||
export default class Entity4 extends IEntity {
|
||||
|
||||
static attributeSeparator = "\n"
|
||||
static keySeparator = " => "
|
||||
static printKey = k => ` \${${k}}`
|
||||
static wrap = (entity, v) => `Begin\n${v}\nEnd`
|
||||
static attributes = {
|
||||
first: new AttributeInfo({
|
||||
type: Entity3,
|
||||
default: new Entity3(),
|
||||
inlined: true,
|
||||
}),
|
||||
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() {
|
||||
super()
|
||||
/** @type {Entity1} */ this.second
|
||||
IEntity.defineAttributes(this.second, {
|
||||
0: {
|
||||
inlined: true,
|
||||
},
|
||||
})
|
||||
...super.attributes,
|
||||
first: Entity3.withDefault().flagInlined(),
|
||||
second: ArrayEntity.of(Entity1).withDefault(type => new type([
|
||||
new (Entity1.flagInlined())({ a: new NumberEntity(1), b: new NumberEntity(2) }),
|
||||
new Entity1({ a: new NumberEntity(11), b: new NumberEntity(22) }),
|
||||
])).flagInlined(),
|
||||
third: ArrayEntity.withDefault(() => new NullEntity()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import AttributeInfo from "../../js/entity/AttributeInfo.js"
|
||||
import IntegerEntity from "../../js/entity/IntegerEntity.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: AttributeInfo.createType(String),
|
||||
key2: AttributeInfo.createType(EntityF),
|
||||
key3: new AttributeInfo({
|
||||
type: IntegerEntity,
|
||||
default: new IntegerEntity(5),
|
||||
silent: true,
|
||||
}),
|
||||
}
|
||||
static grammar = this.createGrammar()
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
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 attributes = {
|
||||
...super.attributes,
|
||||
arg1: AttributeInfo.createType(Number),
|
||||
arg2: AttributeInfo.createType(String),
|
||||
lookbehind: new AttributeInfo({
|
||||
...super.attributes.lookbehind,
|
||||
default: new Union("Foo", "Bar"),
|
||||
})
|
||||
}
|
||||
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
static createGrammar() {
|
||||
return Grammar.createEntityGrammar(this, false)
|
||||
}
|
||||
|
||||
constructor(values = {}) {
|
||||
super(values)
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,93 @@ export default class IssuesNodes1 extends NodeTests {
|
||||
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[3].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="false",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="true",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="true",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))
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Issue 21",
|
||||
title: "Mask ( R )",
|
||||
value: String.raw`
|
||||
Begin Object Class=/Script/UnrealEd.MaterialGraphNode Name="MaterialGraphNode_202" ExportPath=/Script/UnrealEd.MaterialGraphNode'/Engine/Transient.卡通:MaterialGraph_0.MaterialGraphNode_202'
|
||||
Begin Object Class=/Script/Engine.MaterialExpressionSubtract Name="MaterialExpressionSubtract_10" ExportPath=/Script/Engine.MaterialExpressionSubtract'/Engine/Transient.卡通:MaterialGraph_0.MaterialGraphNode_202.MaterialExpressionSubtract_10'
|
||||
End Object
|
||||
Begin Object Name="MaterialExpressionSubtract_10" ExportPath=/Script/Engine.MaterialExpressionSubtract'/Engine/Transient.卡通:MaterialGraph_0.MaterialGraphNode_202.MaterialExpressionSubtract_10'
|
||||
A=(Expression="/Script/Engine.MaterialExpressionSaturate'MaterialGraphNode_237.MaterialExpressionSaturate_3'")
|
||||
B=(Expression="/Script/Engine.MaterialExpressionSaturate'MaterialGraphNode_201.MaterialExpressionSaturate_7'")
|
||||
MaterialExpressionEditorX=0
|
||||
MaterialExpressionEditorY=0
|
||||
MaterialExpressionGuid=7202C13642DA1225C118CF867599387C
|
||||
Material="/Script/UnrealEd.PreviewMaterial'/Engine/Transient.卡通'"
|
||||
End Object
|
||||
MaterialExpression=/Script/Engine.MaterialExpressionSubtract'MaterialExpressionSubtract_10'
|
||||
NodePosX=0
|
||||
NodePosY=0
|
||||
NodeGuid=7008F5AC49E8F5BFD4C707819A58C021
|
||||
CustomProperties Pin (PinId=86D4DE5E48C71A576ED0519B982907B3,PinName="A",PinType.PinCategory="optional",PinType.PinSubCategory="red",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="1",LinkedTo=(),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
|
||||
CustomProperties Pin (PinId=5C75E1374E1E7436C72B9FA072875C04,PinName="B",PinType.PinCategory="optional",PinType.PinSubCategory="red",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="1",LinkedTo=(),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
|
||||
CustomProperties Pin (PinId=528D346A49976B0854764CA755AF2F93,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,LinkedTo=(),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()
|
||||
return [Configuration.rgba.includes(innerText), p]
|
||||
})
|
||||
))
|
||||
|
||||
12
tests/resources/serializedEntity2-1.js
Normal file
12
tests/resources/serializedEntity2-1.js
Normal file
@@ -0,0 +1,12 @@
|
||||
export default `{
|
||||
someNumber: 567
|
||||
someString: "alpha"
|
||||
someString2: "beta"
|
||||
someBoolean: True
|
||||
someBoolean2: False
|
||||
someObjectString: "gamma"
|
||||
someArray: (400,500,600,700,800)
|
||||
someArray2: (-400,-500,-600,-700,-800)
|
||||
someEntity.a: 8
|
||||
someEntity.b: 9
|
||||
}`
|
||||
@@ -6,6 +6,6 @@ export default `{
|
||||
someBoolean2: False
|
||||
someObjectString: "gamma"
|
||||
someArray: (400,500,600,700,800)
|
||||
someArray2: (400,500,600,700,800)
|
||||
someArray2: (-400,-500,-600,-700,-800)
|
||||
someEntity: Entity1(a=8, b=9)
|
||||
}`
|
||||
|
||||
@@ -14,7 +14,6 @@ export default `[[
|
||||
november: 0
|
||||
oscar: Entity1(a=8, b=9)
|
||||
papa: Entity1(a=12, b=13)
|
||||
quebec: 6
|
||||
romeo.a: 8
|
||||
romeo.b: 9
|
||||
sierra.someNumber: 567
|
||||
@@ -24,6 +23,6 @@ export default `[[
|
||||
sierra.someBoolean2: False
|
||||
sierra.someObjectString: "gamma"
|
||||
sierra.someArray: (400,500,600,700,800)
|
||||
sierra.someArray2: (400,500,600,700,800)
|
||||
sierra.someArray2: (-400,-500,-600,-700,-800)
|
||||
sierra.someEntity: Entity1(a=8, b=9)
|
||||
]]`
|
||||
|
||||
@@ -23,7 +23,7 @@ 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.someArray2} => (-400,-500,-600,-700,-800)
|
||||
\${first.sierra.someEntity} => E1[A:8 - B:9]
|
||||
\${second(0).a} => 1
|
||||
\${second(0).b} => 2
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user