import ByteEntity from "./ByteEntity.js" import Configuration from "../Configuration.js" import EnumEntity from "./EnumEntity.js" import FormatTextEntity from "./FormatTextEntity.js" import FunctionReferenceEntity from "./FunctionReferenceEntity.js" import GuidEntity from "./GuidEntity.js" import IEntity from "./IEntity.js" import Integer64Entity from "./Integer64Entity.js" import IntegerEntity from "./IntegerEntity.js" import LinearColorEntity from "./LinearColorEntity.js" import LocalizedTextEntity from "./LocalizedTextEntity.js" import ObjectReferenceEntity from "./ObjectReferenceEntity.js" import PathSymbolEntity from "./PathSymbolEntity.js" import PinReferenceEntity from "./PinReferenceEntity.js" import PinTypeEntity from "./PinTypeEntity.js" import RotatorEntity from "./RotatorEntity.js" import SimpleSerializationRotatorEntity from "./SimpleSerializationRotatorEntity.js" import SimpleSerializationVector2DEntity from "./SimpleSerializationVector2DEntity.js" import SimpleSerializationVectorEntity from "./SimpleSerializationVectorEntity.js" import UnionType from "./UnionType.js" import Utility from "../Utility.js" import Vector2DEntity from "./Vector2DEntity.js" import VectorEntity from "./VectorEntity.js" /** * @typedef {import("./IEntity").AnyValue} AnyValue * @typedef {import("lit").CSSResult} CSSResult */ /** @template {AnyValue} T */ export default class PinEntity extends IEntity { static #typeEntityMap = { "/Script/CoreUObject.LinearColor": LinearColorEntity, "/Script/CoreUObject.Rotator": RotatorEntity, "/Script/CoreUObject.Vector": VectorEntity, "/Script/CoreUObject.Vector2D": Vector2DEntity, "bool": Boolean, "byte": ByteEntity, "enum": EnumEntity, "exec": String, "int": IntegerEntity, "int64": Integer64Entity, "name": String, "real": Number, "string": String, } static #alternativeTypeEntityMap = { "/Script/CoreUObject.Vector2D": SimpleSerializationVector2DEntity, "/Script/CoreUObject.Vector": SimpleSerializationVectorEntity, "/Script/CoreUObject.Rotator": SimpleSerializationRotatorEntity, } static lookbehind = "Pin" static attributes = { "PinId": { type: GuidEntity, }, "PinName": "", "PinFriendlyName": { type: new UnionType(LocalizedTextEntity, FormatTextEntity, String), showDefault: false, }, "PinToolTip": { type: String, showDefault: false, }, "Direction": { type: String, showDefault: false, }, "PinType.PinCategory": "", "PinType.PinSubCategory": "", "PinType.PinSubCategoryObject": { type: ObjectReferenceEntity, }, "PinType.PinSubCategoryMemberReference": { type: FunctionReferenceEntity, value: null, }, "PinType.PinValueType": { type: PinTypeEntity, value: null, }, "PinType.ContainerType": { type: PathSymbolEntity, }, "PinType.bIsReference": false, "PinType.bIsConst": false, "PinType.bIsWeakPointer": false, "PinType.bIsUObjectWrapper": false, "PinType.bSerializeAsSinglePrecisionFloat": false, "LinkedTo": { type: [PinReferenceEntity], showDefault: false, }, "DefaultValue": { /** @param {PinEntity} pinEntity */ type: pinEntity => pinEntity.getEntityType(true) ?? String, serialized: true, showDefault: false, }, "AutogeneratedDefaultValue": { type: String, showDefault: false, }, "DefaultObject": { type: ObjectReferenceEntity, showDefault: false, value: null, }, "PersistentGuid": { type: GuidEntity, }, "bHidden": false, "bNotConnectable": false, "bDefaultValueIsReadOnly": false, "bDefaultValueIsIgnored": false, "bAdvancedView": false, "bOrphanedPin": false, } static { this.cleanupAttributes(this.attributes) } constructor(values = {}, suppressWarns = false) { super(values, suppressWarns) this["PinId"] ??= /** @type {GuidEntity} */(undefined) this["PinName"] ??= /** @type {String} */(undefined) this["PinFriendlyName"] ??= /** @type {LocalizedTextEntity | String} */(undefined) this["PinToolTip"] ??= /** @type {String} */(undefined) this["Direction"] ??= /** @type {String} */(undefined) this["PinType.PinCategory"] ??= /** @type {String} */(undefined) this["PinType.PinSubCategory"] ??= /** @type {String} */(undefined) this["PinType.PinSubCategoryObject"] ??= /** @type {ObjectReferenceEntity} */(undefined) this["PinType.PinSubCategoryMemberReference"] ??= /** @type {FunctionReferenceEntity} */(undefined) this["PinType.PinValueType"] ??= /** @type {PinTypeEntity} */(undefined) this["PinType.ContainerType"] ??= /** @type {PathSymbolEntity} */(undefined) this["PinType.bIsReference"] ??= /** @type {Boolean} */(undefined) this["PinType.bIsConst"] ??= /** @type {Boolean} */(undefined) this["PinType.bIsWeakPointer"] ??= /** @type {Boolean} */(undefined) this["PinType.bIsUObjectWrapper"] ??= /** @type {Boolean} */(undefined) this["PinType.bIsUObjectWrapper"] ??= /** @type {Boolean} */(undefined) this["LinkedTo"] ??= /** @type {PinReferenceEntity[]} */(undefined) this["DefaultValue"] ??= /** @type {T} */(undefined) this["AutogeneratedDefaultValue"] ??= /** @type {String} */(undefined) this["DefaultObject"] ??= /** @type {ObjectReferenceEntity} */(undefined) this["PersistentGuid"] ??= /** @type {GuidEntity} */(undefined) this["bHidden"] ??= /** @type {Boolean} */(undefined) this["bNotConnectable"] ??= /** @type {Boolean} */(undefined) this["bDefaultValueIsReadOnly"] ??= /** @type {Boolean} */(undefined) this["bDefaultValueIsIgnored"] ??= /** @type {Boolean} */(undefined) this["bAdvancedView"] ??= /** @type {Boolean} */(undefined) this["bOrphanedPin"] ??= /** @type {Boolean} */(undefined) } getType() { const subCategory = this["PinType.PinSubCategoryObject"] if (this["PinType.PinCategory"] === "struct" || this["PinType.PinCategory"] === "object") { return subCategory.path } if ( this["PinType.PinCategory"] === "byte" && ( subCategory.type === Configuration.nodeType.enum || subCategory.type === Configuration.nodeType.userDefinedEnum ) ) { return "enum" } return this["PinType.PinCategory"] } getEntityType(alternative = false) { const typeString = this.getType() const entity = PinEntity.#typeEntityMap[typeString] const alternativeEntity = PinEntity.#alternativeTypeEntityMap[typeString] return alternative && alternativeEntity !== undefined ? alternativeEntity : entity } getDisplayName() { let matchResult = null if ( this["PinToolTip"] // Match up until the first \n excluded or last character && (matchResult = this["PinToolTip"].match(/\s*(.+?(?=\n)|.+\S)\s*/)) ) { return Utility.formatStringName(matchResult[1]) } return Utility.formatStringName(this["PinName"]) } /** @param {PinEntity} other */ copyTypeFrom(other) { this["PinType.PinCategory"] = other["PinType.PinCategory"] this["PinType.PinSubCategory"] = other["PinType.PinSubCategory"] this["PinType.PinSubCategoryObject"] = other["PinType.PinSubCategoryObject"] this["PinType.PinSubCategoryMemberReference"] = other["PinType.PinSubCategoryMemberReference"] this["PinType.PinValueType"] = other["PinType.PinValueType"] this["PinType.ContainerType"] = other["PinType.ContainerType"] this["PinType.bIsReference"] = other["PinType.bIsReference"] this["PinType.bIsConst"] = other["PinType.bIsConst"] this["PinType.bIsWeakPointer"] = other["PinType.bIsWeakPointer"] this["PinType.bIsUObjectWrapper"] = other["PinType.bIsUObjectWrapper"] this["PinType.bSerializeAsSinglePrecisionFloat"] = other["PinType.bSerializeAsSinglePrecisionFloat"] } getDefaultValue(maybeCreate = false) { if (this["DefaultValue"] === undefined && maybeCreate) { this["DefaultValue"] = new (this.getEntityType(true))() } return this["DefaultValue"] } isExecution() { return this["PinType.PinCategory"] === "exec" } isHidden() { return this["bHidden"] } isInput() { return !this["bHidden"] && this["Direction"] != "EGPD_Output" } isOutput() { return !this["bHidden"] && this["Direction"] == "EGPD_Output" } isLinked() { return this.LinkedTo?.length > 0 ?? false } /** * @param {String} targetObjectName * @param {PinEntity} targetPinEntity */ linkTo(targetObjectName, targetPinEntity) { const linkFound = this.LinkedTo?.some(pinReferenceEntity => pinReferenceEntity.objectName.toString() == targetObjectName && pinReferenceEntity.pinGuid.valueOf() == targetPinEntity["PinId"].valueOf() ) if (!linkFound) { (this.LinkedTo ??= []).push(new PinReferenceEntity({ objectName: targetObjectName, pinGuid: targetPinEntity["PinId"], })) return true } return false // Already linked } /** * @param {String} targetObjectName * @param {PinEntity} targetPinEntity */ unlinkFrom(targetObjectName, targetPinEntity) { const indexElement = this.LinkedTo?.findIndex(pinReferenceEntity => { return pinReferenceEntity.objectName.toString() == targetObjectName && pinReferenceEntity.pinGuid.valueOf() == targetPinEntity["PinId"].valueOf() }) if (indexElement >= 0) { this.LinkedTo.splice(indexElement, 1) if (this.LinkedTo.length === 0 && !PinEntity.attributes.LinkedTo.showDefault) { this.LinkedTo = undefined } return true } return false } getSubCategory() { return this["PinType.PinSubCategoryObject"].path } /** @return {CSSResult} */ pinColor() { return Configuration.pinColor[this.getType()] ?? Configuration.pinColor[this["PinType.PinCategory"]] ?? Configuration.pinColor["default"] } }