Files
ueblueprint/js/element/PinElement.js
barsdeveloper 7469d55518 Replace parsing and test libraries
* WIP

* WIP

* wip

* WIP

* Several fixes

* Tests wip port to playwright

* WIP

* Fix more tests

* Serialization tests fixed

* Several fixes for tests

* Input options types

* Type adjustments

* Fix object reference parser

* Tests fixes

* More tests fixes
2024-02-14 00:40:42 +01:00

278 lines
9.2 KiB
JavaScript

import BoolPinTemplate from "../template/pin/BoolPinTemplate.js"
import Configuration from "../Configuration.js"
import ElementFactory from "./ElementFactory.js"
import EnumPinTemplate from "../template/pin/EnumPinTemplate.js"
import ExecPinTemplate from "../template/pin/ExecPinTemplate.js"
import GuidEntity from "../entity/GuidEntity.js"
import IElement from "./IElement.js"
import Int64PinTemplate from "../template/pin/Int64PinTemplate.js"
import IntPinTemplate from "../template/pin/IntPinTemplate.js"
import LinearColorEntity from "../entity/LinearColorEntity.js"
import LinearColorPinTemplate from "../template/pin/LinearColorPinTemplate.js"
import NamePinTemplate from "../template/pin/NamePinTemplate.js"
import PinEntity from "../entity/PinEntity.js"
import PinReferenceEntity from "../entity/PinReferenceEntity.js"
import PinTemplate from "../template/pin/PinTemplate.js"
import RealPinTemplate from "../template/pin/RealPinTemplate.js"
import ReferencePinTemplate from "../template/pin/ReferencePinTemplate.js"
import RotatorPinTemplate from "../template/pin/RotatorPinTemplate.js"
import StringPinTemplate from "../template/pin/StringPinTemplate.js"
import Utility from "../Utility.js"
import Vector2DPinTemplate from "../template/pin/Vector2DPinTemplate.js"
import VectorPinTemplate from "../template/pin/VectorPinTemplate.js"
/**
* @template {TerminalAttribute} T
* @extends {IElement<PinEntity<T>, PinTemplate>}
*/
export default class PinElement extends IElement {
static #inputPinTemplates = {
"bool": BoolPinTemplate,
"byte": IntPinTemplate,
"enum": EnumPinTemplate,
"int": IntPinTemplate,
"int64": Int64PinTemplate,
"MUTABLE_REFERENCE": ReferencePinTemplate,
"name": NamePinTemplate,
"rg": Vector2DPinTemplate,
"real": RealPinTemplate,
"string": StringPinTemplate,
[Configuration.paths.linearColor]: LinearColorPinTemplate,
[Configuration.paths.rotator]: RotatorPinTemplate,
[Configuration.paths.vector]: VectorPinTemplate,
[Configuration.paths.vector2D]: Vector2DPinTemplate,
}
static properties = {
pinId: {
type: GuidEntity,
converter: {
fromAttribute: (value, type) => value
? GuidEntity.grammar.parse(value)
: null,
toAttribute: (value, type) => /** @type {String} */(value?.toString()),
},
attribute: "data-id",
reflect: true,
},
pinType: {
type: String,
attribute: "data-type",
reflect: true,
},
advancedView: {
type: String,
attribute: "data-advanced-view",
reflect: true,
},
color: {
type: LinearColorEntity,
converter: {
fromAttribute: (value, type) => value
? LinearColorEntity.getLinearColorFromAnyFormat().parse(value)
: null,
toAttribute: (value, type) => value ? Utility.printLinearColor(value) : null,
},
attribute: "data-color",
reflect: true,
},
defaultValue: {
type: String,
attribute: false,
},
isLinked: {
type: Boolean,
converter: Utility.booleanConverter,
attribute: "data-linked",
reflect: true,
},
pinDirection: {
type: String,
attribute: "data-direction",
reflect: true,
},
connectable: {
type: Boolean,
converter: Utility.booleanConverter,
attribute: "data-connectable",
reflect: true,
}
}
/** @type {NodeElement} */
nodeElement
/** @param {PinEntity<any>} pinEntity */
static getTypeTemplate(pinEntity) {
if (pinEntity.PinType.ContainerType?.toString() === "Array") {
return PinTemplate
}
if (pinEntity.PinType.bIsReference && !pinEntity.PinType.bIsConst) {
return PinElement.#inputPinTemplates["MUTABLE_REFERENCE"]
}
if (pinEntity.getType() === "exec") {
return ExecPinTemplate
}
return (pinEntity.isInput() ? PinElement.#inputPinTemplates[pinEntity.getType()] : PinTemplate) ?? PinTemplate
}
static newObject(
entity = new PinEntity(),
template = /** @type {PinTemplate} */(new (PinElement.getTypeTemplate(entity))()),
nodeElement = undefined
) {
const result = new PinElement()
result.initialize(entity, template, nodeElement)
return result
}
initialize(
entity = /** @type {PinEntity<T>} */(new PinEntity()),
template = /** @type {PinTemplate} */(new (PinElement.getTypeTemplate(entity))()),
nodeElement = undefined
) {
this.nodeElement = nodeElement
this.advancedView = entity.bAdvancedView
this.isLinked = false
this.connectable = !entity.bNotConnectable
super.initialize(entity, template)
this.pinType = this.entity.getType()
this.defaultValue = this.entity.getDefaultValue()
this.color = PinElement.properties.color.converter.fromAttribute(this.getColor().toString())
this.pinDirection = entity.isInput() ? "input" : entity.isOutput() ? "output" : "hidden"
}
setup() {
super.setup()
this.nodeElement = this.closest("ueb-node")
}
createPinReference() {
return new PinReferenceEntity({
objectName: this.nodeElement.getNodeName(),
pinGuid: this.getPinId(),
})
}
/** @return {GuidEntity} */
getPinId() {
return this.entity.PinId
}
/** @returns {String} */
getPinName() {
return this.entity.PinName
}
getPinDisplayName() {
return this.entity.pinDisplayName()
}
/** @return {CSSResult} */
getColor() {
return this.entity.pinColor()
}
isInput() {
return this.entity.isInput()
}
isOutput() {
return this.entity.isOutput()
}
getLinkLocation() {
return this.template.getLinkLocation()
}
getNodeElement() {
return this.nodeElement
}
getLinks() {
return this.entity.LinkedTo ?? []
}
getDefaultValue(maybeCreate = false) {
return this.defaultValue = this.entity.getDefaultValue(maybeCreate)
}
/** @param {T} value */
setDefaultValue(value) {
this.entity.DefaultValue = value
this.defaultValue = value
}
/** @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
}
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
})
this.isLinked = this.entity.isLinked()
}
/** @param {PinElement} targetPinElement */
linkTo(targetPinElement) {
const pinReference = this.createPinReference()
if (
this.isLinked
&& this.isOutput()
&& (this.pinType === "exec" || targetPinElement.pinType === "exec")
&& !this.getLinks().some(ref => pinReference.equals(ref))) {
this.unlinkFromAll()
}
if (this.entity.linkTo(targetPinElement.getNodeElement().getNodeName(), targetPinElement.entity)) {
this.isLinked = this.entity.isLinked()
this.nodeElement?.template.linksChanged()
}
}
/** @param {PinElement} targetPinElement */
unlinkFrom(targetPinElement, removeLink = true) {
if (this.entity.unlinkFrom(targetPinElement.getNodeElement().getNodeName(), targetPinElement.entity)) {
this.isLinked = this.entity.isLinked()
this.nodeElement?.template.linksChanged()
if (removeLink) {
this.blueprint.getLink(this, targetPinElement)?.remove() // Might be called after the link is removed
}
}
}
unlinkFromAll() {
const isLinked = this.getLinks().length
this.getLinks().map(ref => this.blueprint.getPin(ref)).forEach(pin => this.unlinkFrom(pin))
if (isLinked) {
this.nodeElement?.template.linksChanged()
}
}
/**
* @param {PinElement} originalPinElement
* @param {PinReferenceEntity} newReference
*/
redirectLink(originalPinElement, newReference) {
const index = this.getLinks().findIndex(pinReference =>
pinReference.objectName.toString() == originalPinElement.getNodeElement().getNodeName()
&& pinReference.pinGuid.valueOf() == originalPinElement.entity.PinId.valueOf()
)
if (index >= 0) {
this.entity.LinkedTo[index] = newReference
return true
}
return false
}
}