Merge remote-tracking branch 'origin/master' into mirrored-object-reference-fix

This commit is contained in:
barsdeveloper
2024-11-06 20:32:42 +01:00
28 changed files with 424 additions and 168 deletions

View File

@@ -740,11 +740,6 @@ ueb-pin[data-connectable=false] .ueb-pin-icon {
visibility: hidden;
}
.ueb-node-style-event ueb-pin[data-type=delegate] .ueb-pin-icon {
width: 11px;
height: 11px;
}
.ueb-node-inputs .ueb-pin-icon {
margin-right: 6px;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

195
dist/ueblueprint.js vendored
View File

@@ -130,6 +130,7 @@ class Configuration {
callArrayFunction: "/Script/BlueprintGraph.K2Node_CallArrayFunction",
callDelegate: "/Script/BlueprintGraph.K2Node_CallDelegate",
callFunction: "/Script/BlueprintGraph.K2Node_CallFunction",
clearDelegate: "/Script/BlueprintGraph.K2Node_ClearDelegate",
comment: "/Script/UnrealEd.EdGraphNode_Comment",
commutativeAssociativeBinaryOperator: "/Script/BlueprintGraph.K2Node_CommutativeAssociativeBinaryOperator",
componentBoundEvent: "/Script/BlueprintGraph.K2Node_ComponentBoundEvent",
@@ -218,6 +219,7 @@ class Configuration {
pcgSubgraphSettings: "/Script/PCG.PCGSubgraphSettings",
promotableOperator: "/Script/BlueprintGraph.K2Node_PromotableOperator",
quat4f: "/Script/CoreUObject.Quat4f",
removeDelegate: "/Script/BlueprintGraph.K2Node_RemoveDelegate",
reverseForEachLoop: "/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:ReverseForEachLoop",
rotator: "/Script/CoreUObject.Rotator",
select: "/Script/BlueprintGraph.K2Node_Select",
@@ -982,7 +984,7 @@ class SVGIcon {
`
static delegate = x`
<svg viewBox="-2 -2 32 32" xmlns="http://www.w3.org/2000/svg">
<svg width="11" height="11" viewBox="-2 -2 32 32" xmlns="http://www.w3.org/2000/svg">
<rect class="ueb-pin-tofill" fill="black" width="28" height="28" rx="4" stroke="currentColor" stroke-width="5" />
</svg>
`
@@ -2685,6 +2687,14 @@ class IEntity {
this.#ignored = value;
}
#inlined = /** @type {typeof IEntity} */(this.constructor).inlined
get inlined() {
return this.#inlined
}
set inlined(value) {
this.#inlined = value;
}
#quoted
get quoted() {
return this.#quoted ?? /** @type {typeof IEntity} */(this.constructor).quoted ?? false
@@ -2955,7 +2965,7 @@ class IEntity {
if (keyValue.length && (Self.attributes[key]?.quoted || value.quoted)) {
keyValue = `"${keyValue}"`;
}
if (valueType.inlined) {
if (value.inlined) {
const inlinedPrintKey = valueType.className() === "ArrayEntity"
? k => printKey(`${keyValue}${k}`)
: k => printKey(`${keyValue}.${k}`);
@@ -3271,9 +3281,17 @@ class Grammar {
const attributeKey = attributeName.split(Configuration.keysSeparator);
const attributeValue = this.getAttribute(entityType, attributeKey);
const grammar = attributeValue ? attributeValue.grammar : IEntity.unknownEntityGrammar;
const inlined = attributeKey.length > 1;
return grammar.map(attributeValue =>
values => {
Utility.objectSet(values, attributeKey, attributeValue);
attributeKey.reduce(
(acc, cur, i) => {
acc[cur]["inlined"] = inlined && i < attributeKey.length - 1;
return acc[cur]
},
values
);
handleObjectSet(values, attributeKey, attributeValue);
}
)
@@ -4026,8 +4044,17 @@ function keyName(value) {
* @returns {String}
*/
function nodeTitle(entity) {
let input;
let value;
switch (entity.getType()) {
case Configuration.paths.addDelegate:
value ??= "Bind Event to ";
case Configuration.paths.clearDelegate:
value ??= "Unbind all Events from ";
case Configuration.paths.removeDelegate:
value ??= "Unbind Event from ";
return value + Utility.formatStringName(
entity.DelegateReference?.MemberName?.toString().replace(/Delegate$/, "") ?? "None"
)
case Configuration.paths.asyncAction:
if (entity.ProxyFactoryFunctionName) {
return Utility.formatStringName(entity.ProxyFactoryFunctionName?.toString())
@@ -4080,25 +4107,26 @@ function nodeTitle(entity) {
}
}
case Configuration.paths.materialExpressionConstant:
input ??= [entity.getCustomproperties().find(pinEntity => pinEntity.PinName.toString() == "Value")?.DefaultValue];
value ??= [entity.getCustomproperties().find(pinEntity => pinEntity.PinName.toString() == "Value")?.DefaultValue];
case Configuration.paths.materialExpressionConstant2Vector:
input ??= [
value ??= [
entity.getCustomproperties().find(pinEntity => pinEntity.PinName?.toString() == "X")?.DefaultValue,
entity.getCustomproperties().find(pinEntity => pinEntity.PinName?.toString() == "Y")?.DefaultValue,
];
case Configuration.paths.materialExpressionConstant3Vector:
case Configuration.paths.materialExpressionConstant4Vector:
if (!input) {
if (!value) {
const vector = entity.getCustomproperties()
.find(pinEntity => pinEntity.PinName?.toString() == "Constant")
?.DefaultValue;
input = vector instanceof VectorEntity ? [vector.X, vector.Y, vector.Z].map(v => v.valueOf())
value = 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)).join(",")
if (value?.length > 0) {
return value.map(v => Utility.printExponential(v)).join(",")
}
value = undefined;
break
case Configuration.paths.materialExpressionFunctionInput: {
const materialObject = entity.getMaterialSubobject();
@@ -4412,9 +4440,11 @@ function nodeIcon(entity) {
case Configuration.paths.addDelegate:
case Configuration.paths.asyncAction:
case Configuration.paths.callDelegate:
case Configuration.paths.clearDelegate:
case Configuration.paths.createDelegate:
case Configuration.paths.functionEntry:
case Configuration.paths.functionResult:
case Configuration.paths.removeDelegate:
return SVGIcon.node
case Configuration.paths.customEvent: return SVGIcon.event
case Configuration.paths.doN: return SVGIcon.doN
@@ -4726,7 +4756,7 @@ const pinColorMaterial = i$3`120, 120, 120`;
/** @param {PinEntity<IEntity>} entity */
function pinColor(entity) {
if (entity.PinType.PinCategory?.toString() === "mask") {
const result = colors[entity.PinType.PinSubCategory];
const result = colors[entity.PinType.PinSubCategory?.toString()];
if (result) {
return result
}
@@ -5294,7 +5324,7 @@ class PinTypeEntity extends IEntity {
static attributes = {
...super.attributes,
PinCategory: StringEntity.withDefault(),
PinSubCategory: StringEntity.withDefault(),
PinSubCategory: StringEntity,
PinSubCategoryObject: ObjectReferenceEntity,
PinSubCategoryMemberReference: FunctionReferenceEntity,
ContainerType: SymbolEntity,
@@ -5657,11 +5687,11 @@ class PinEntity extends IEntity {
AutogeneratedDefaultValue: StringEntity,
DefaultObject: ObjectReferenceEntity,
PersistentGuid: GuidEntity,
bHidden: BooleanEntity.withDefault(),
bNotConnectable: BooleanEntity.withDefault(),
bDefaultValueIsReadOnly: BooleanEntity.withDefault(),
bDefaultValueIsIgnored: BooleanEntity.withDefault(),
bAdvancedView: BooleanEntity.withDefault(),
bHidden: BooleanEntity,
bNotConnectable: BooleanEntity,
bDefaultValueIsReadOnly: BooleanEntity,
bDefaultValueIsIgnored: BooleanEntity,
bAdvancedView: BooleanEntity,
bOrphanedPin: BooleanEntity,
}
static grammar = this.createGrammar()
@@ -6121,12 +6151,18 @@ class ScriptVariableEntity extends IEntity {
class UnknownPinEntity extends PinEntity {
static attributes = {
...super.attributes,
PinId: GuidEntity
}
static grammar = this.createGrammar()
/** @returns {P<UnknownPinEntity>} */
static createGrammar() {
return Parsernostrum.seq(
Parsernostrum.reg(new RegExp(`(${Grammar.Regex.Symbol.source})\\s*\\(\\s*`), 1),
// Lookbehind
Parsernostrum.reg(new RegExp(`(${Grammar.Regex.Symbol.source}\\s*)\\(\\s*`), 1),
Grammar.createAttributeGrammar(this).sepBy(Grammar.commaSeparation),
Parsernostrum.reg(/\s*(?:,\s*)?\)/)
).map(([lookbehind, attributes, _2]) => {
@@ -8475,6 +8511,29 @@ class MouseClickDrag extends MouseMoveDraggable {
}
}
/**
* @param {ObjectEntity} entity
* @returns {String?}
*/
function nodeSubtitle(entity) {
switch (entity.getType()) {
case Configuration.paths.addDelegate:
case Configuration.paths.clearDelegate:
case Configuration.paths.removeDelegate:
return null
}
const targetPin = entity
.getPinEntities()
.find(pin => pin.PinName?.toString() === "self" && pinTitle(pin) === "Target");
if (targetPin) {
const target = entity.FunctionReference?.MemberParent?.getName()
?? targetPin.PinType?.PinSubCategoryObject?.getName()
?? "Untitled";
return target.length > 0 ? `Target is ${Utility.formatStringName(target)}` : null
}
return null
}
/** @typedef {import("./IMouseClickDrag.js").Options} Options */
/** @extends {MouseMoveDraggable<NodeElement>} */
@@ -8646,7 +8705,7 @@ class NodeTemplate extends ISelectableDraggableTemplate {
static nodeStyleClasses = ["ueb-node-style-default"]
#hasSubtitle = false
#subtitle
/** @type {() => PinEntity<IEntity>} */
pinInserter
@@ -8692,6 +8751,7 @@ class NodeTemplate extends ISelectableDraggableTemplate {
/** @param {NodeElement} element */
initialize(element) {
super.initialize(element);
this.#subtitle = nodeSubtitle(element.entity);
this.element.classList.add(.../** @type {typeof NodeTemplate} */(this.constructor).nodeStyleClasses);
this.element.style.setProperty("--ueb-node-color", this.getColor().cssText);
this.pinInserter = this.element.entity.additionalPinInserter();
@@ -8750,10 +8810,8 @@ class NodeTemplate extends ISelectableDraggableTemplate {
${name ? x`
<div class="ueb-node-name-text ueb-ellipsis-nowrap-text">
${name}
${this.#hasSubtitle && this.getTargetType().length > 0 ? x`
<div class="ueb-node-subtitle-text ueb-ellipsis-nowrap-text">
Target is ${Utility.formatStringName(this.getTargetType())}
</div>
${this.#subtitle ? x`
<div class="ueb-node-subtitle-text ueb-ellipsis-nowrap-text">${this.#subtitle}</div>
`: A}
</div>
` : A}
@@ -8774,7 +8832,7 @@ class NodeTemplate extends ISelectableDraggableTemplate {
this.element.nodeNameElement = /** @type {HTMLElement} */(this.element.querySelector(".ueb-node-name-text"));
let hasInput = false;
let hasOutput = false;
for (const p of this.element.getPinElements()) {
for (const p of this.getPinElements()) {
if (p === this.defaultPin) {
continue
}
@@ -8797,26 +8855,14 @@ class NodeTemplate extends ISelectableDraggableTemplate {
}
}
getPinElements() {
return this.element.getPinElements()
}
createPinElements() {
return this.element.getPinEntities()
.filter(v => !v.isHidden())
.map(pinEntity => {
this.#hasSubtitle = this.#hasSubtitle
|| pinEntity.PinName.toString() === "self" && pinEntity.pinTitle() === "Target";
return this.createPinElement(pinEntity)
})
}
getTargetType() {
return this.element.entity.FunctionReference?.MemberParent?.getName() ?? "Untitled"
}
/**
* @param {NodeElement} node
* @returns {NodeListOf<PinElement>}
*/
getPinElements(node) {
return node.querySelectorAll("ueb-pin")
.map(pinEntity => this.createPinElement(pinEntity))
}
linksChanged() { }
@@ -9385,12 +9431,12 @@ class PinTemplate extends ITemplate {
return SVGIcon.pcgStackPin
}
}
switch (this.element.entity.PinType?.ContainerType?.serialize()) {
switch (this.element.entity.PinType.ContainerType?.toString()) {
case "Array": return SVGIcon.arrayPin
case "Set": return SVGIcon.setPin
case "Map": return SVGIcon.mapPin
}
if (this.element.entity.PinType?.PinCategory?.toString().toLocaleLowerCase() === "delegate") {
if (this.element.entity.PinType.PinCategory?.toString().toLocaleLowerCase() === "delegate") {
return SVGIcon.delegate
}
if (this.element.nodeElement?.template instanceof VariableOperationNodeTemplate) {
@@ -9474,6 +9520,7 @@ class MinimalPinTemplate extends PinTemplate {
class EventNodeTemplate extends NodeTemplate {
static nodeStyleClasses = [...super.nodeStyleClasses, "ueb-node-style-event"]
#delegatePinElement
/** @param {PropertyValues} changedProperties */
firstUpdated(changedProperties) {
@@ -9505,22 +9552,32 @@ class EventNodeTemplate extends NodeTemplate {
`
}
getPinElements() {
return this.element.getPinElements().filter(v => v.entity.PinType.PinCategory?.toString() !== "delegate")
}
createDelegatePinElement() {
const pin = /** @type {PinElementConstructor} */(ElementFactory.getConstructor("ueb-pin")).newObject(
this.element.getPinEntities().find(v => !v.isHidden() && v.PinType.PinCategory?.toString() === "delegate"),
new MinimalPinTemplate(),
this.element
);
pin.template.isNameRendered = false;
return pin
if (!this.#delegatePinElement) {
this.#delegatePinElement = /** @type {PinElementConstructor} */(ElementFactory.getConstructor("ueb-pin"))
.newObject(
this.element.getPinEntities().find(v => !v.isHidden() && v.PinType.PinCategory?.toString() === "delegate"),
new MinimalPinTemplate(),
this.element
);
this.#delegatePinElement.template.isNameRendered = false;
}
return this.#delegatePinElement
}
createPinElements() {
return this.element.getPinEntities()
.filter(v => !v.isHidden() && v.PinType.PinCategory?.toString() !== "delegate")
.map(pinEntity => /** @type {PinElementConstructor} */(ElementFactory.getConstructor("ueb-pin"))
.newObject(pinEntity, undefined, this.element)
)
return [
this.createDelegatePinElement(),
...this.element.getPinEntities()
.filter(v => !v.isHidden() && v.PinType.PinCategory?.toString() !== "delegate")
.map(pinEntity => /** @type {PinElementConstructor} */(ElementFactory.getConstructor("ueb-pin"))
.newObject(pinEntity, undefined, this.element)
)
]
}
}
@@ -9600,17 +9657,9 @@ class KnotNodeTemplate extends NodeTemplate {
}
setupPins() {
this.element.getPinElements().forEach(
p => /** @type {HTMLElement} */(this.element.querySelector(".ueb-node-border")).appendChild(p)
);
}
/**
* @param {NodeElement} node
* @returns {NodeListOf<PinElement>}
*/
getPinElements(node) {
return node.querySelectorAll("ueb-pin")
for (const p of this.getPinElements()) {
/** @type {HTMLElement} */(this.element.querySelector(".ueb-node-border")).appendChild(p);
}
}
createPinElements() {
@@ -9915,7 +9964,7 @@ class NodeElement extends ISelectableDraggableElement {
}
/** @param {String} name */
#redirectLinksAfterRename(name) {
#redirectLinksBeforeRename(name) {
for (let sourcePinElement of this.getPinElements()) {
for (let targetPinReference of sourcePinElement.getLinks()) {
this.blueprint.getPin(targetPinReference).redirectLink(
@@ -9950,9 +9999,9 @@ class NodeElement extends ISelectableDraggableElement {
"Name",
/** @param {InstanceType<typeof ObjectEntity.attributes.Name>} newName */
newName => {
this.#redirectLinksBeforeRename(newName.value);
this.nodeTitle = newName.value;
this.nodeDisplayName = nodeTitle(entity);
this.#redirectLinksAfterRename(newName.value);
}
);
}
@@ -10067,7 +10116,7 @@ class BlueprintEntity extends ObjectEntity {
/** @param {ObjectEntity} entity */
getHomonymObjectEntity(entity) {
const name = entity.getObjectName(false);
const name = entity.getObjectName();
return this.#objectEntities.find(entity => entity.getObjectName() == name)
}
@@ -11319,8 +11368,9 @@ class Blueprint extends IElement {
const name = element.entity.getObjectName();
const homonym = this.entity.getHomonymObjectEntity(element.entity);
if (homonym) {
homonym.Name.value = this.entity.takeFreeName(name);
homonym.Name = homonym.Name;
const newName = this.entity.takeFreeName(name);
// @ts-expect-error
homonym.Name = new (homonym.Name.constructor)(newName);
}
this.nodes.push(element);
this.entity.addObjectEntity(element.entity);
@@ -12848,7 +12898,7 @@ class PinElement extends IElement {
fromAttribute: (value, type) => value
? GuidEntity.grammar.parse(value)
: null,
toAttribute: (value, type) => /** @type {String} */(value?.toString()),
toAttribute: (value, type) => value?.toString(),
},
attribute: "data-id",
reflect: true,
@@ -12920,6 +12970,7 @@ class PinElement extends IElement {
this.isLinked = false;
this.connectable = !entity.bNotConnectable?.valueOf();
super.initialize(entity, template);
this.pinId = this.entity.PinId;
this.pinType = this.entity.getType();
this.defaultValue = this.entity.getDefaultValue();
this.color = PinElement.properties.color.converter.fromAttribute(this.getColor().toString());
@@ -13058,7 +13109,7 @@ class PinElement extends IElement {
&& pinReference.pinGuid.toString() == originalPinElement.entity.PinId.toString()
);
if (index >= 0) {
this.entity.LinkedTo[index] = newReference;
this.entity.LinkedTo.valueOf()[index] = newReference;
return true
}
return false

File diff suppressed because one or more lines are too long

View File

@@ -420,8 +420,9 @@ export default class Blueprint extends IElement {
const name = element.entity.getObjectName()
const homonym = this.entity.getHomonymObjectEntity(element.entity)
if (homonym) {
homonym.Name.value = this.entity.takeFreeName(name)
homonym.Name = homonym.Name
const newName = this.entity.takeFreeName(name)
// @ts-expect-error
homonym.Name = new (homonym.Name.constructor)(newName)
}
this.nodes.push(element)
this.entity.addObjectEntity(element.entity)

View File

@@ -106,6 +106,7 @@ export default class Configuration {
callArrayFunction: "/Script/BlueprintGraph.K2Node_CallArrayFunction",
callDelegate: "/Script/BlueprintGraph.K2Node_CallDelegate",
callFunction: "/Script/BlueprintGraph.K2Node_CallFunction",
clearDelegate: "/Script/BlueprintGraph.K2Node_ClearDelegate",
comment: "/Script/UnrealEd.EdGraphNode_Comment",
commutativeAssociativeBinaryOperator: "/Script/BlueprintGraph.K2Node_CommutativeAssociativeBinaryOperator",
componentBoundEvent: "/Script/BlueprintGraph.K2Node_ComponentBoundEvent",
@@ -194,6 +195,7 @@ export default class Configuration {
pcgSubgraphSettings: "/Script/PCG.PCGSubgraphSettings",
promotableOperator: "/Script/BlueprintGraph.K2Node_PromotableOperator",
quat4f: "/Script/CoreUObject.Quat4f",
removeDelegate: "/Script/BlueprintGraph.K2Node_RemoveDelegate",
reverseForEachLoop: "/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:ReverseForEachLoop",
rotator: "/Script/CoreUObject.Rotator",
select: "/Script/BlueprintGraph.K2Node_Select",

View File

@@ -67,7 +67,7 @@ export default class SVGIcon {
`
static delegate = html`
<svg viewBox="-2 -2 32 32" xmlns="http://www.w3.org/2000/svg">
<svg width="11" height="11" viewBox="-2 -2 32 32" xmlns="http://www.w3.org/2000/svg">
<rect class="ueb-pin-tofill" fill="black" width="28" height="28" rx="4" stroke="currentColor" stroke-width="5" />
</svg>
`

View File

@@ -11,9 +11,11 @@ export default function nodeIcon(entity) {
case Configuration.paths.addDelegate:
case Configuration.paths.asyncAction:
case Configuration.paths.callDelegate:
case Configuration.paths.clearDelegate:
case Configuration.paths.createDelegate:
case Configuration.paths.functionEntry:
case Configuration.paths.functionResult:
case Configuration.paths.removeDelegate:
return SVGIcon.node
case Configuration.paths.customEvent: return SVGIcon.event
case Configuration.paths.doN: return SVGIcon.doN

View File

@@ -0,0 +1,26 @@
import Configuration from "../Configuration.js"
import Utility from "../Utility.js"
import pinTitle from "./pinTitle.js"
/**
* @param {ObjectEntity} entity
* @returns {String?}
*/
export default function nodeSubtitle(entity) {
switch (entity.getType()) {
case Configuration.paths.addDelegate:
case Configuration.paths.clearDelegate:
case Configuration.paths.removeDelegate:
return null
}
const targetPin = entity
.getPinEntities()
.find(pin => pin.PinName?.toString() === "self" && pinTitle(pin) === "Target")
if (targetPin) {
const target = entity.FunctionReference?.MemberParent?.getName()
?? targetPin.PinType?.PinSubCategoryObject?.getName()
?? "Untitled"
return target.length > 0 ? `Target is ${Utility.formatStringName(target)}` : null
}
return null
}

View File

@@ -76,8 +76,17 @@ function keyName(value) {
* @returns {String}
*/
export default function nodeTitle(entity) {
let input
let value
switch (entity.getType()) {
case Configuration.paths.addDelegate:
value ??= "Bind Event to "
case Configuration.paths.clearDelegate:
value ??= "Unbind all Events from "
case Configuration.paths.removeDelegate:
value ??= "Unbind Event from "
return value + Utility.formatStringName(
entity.DelegateReference?.MemberName?.toString().replace(/Delegate$/, "") ?? "None"
)
case Configuration.paths.asyncAction:
if (entity.ProxyFactoryFunctionName) {
return Utility.formatStringName(entity.ProxyFactoryFunctionName?.toString())
@@ -130,25 +139,26 @@ export default function nodeTitle(entity) {
}
}
case Configuration.paths.materialExpressionConstant:
input ??= [entity.getCustomproperties().find(pinEntity => pinEntity.PinName.toString() == "Value")?.DefaultValue]
value ??= [entity.getCustomproperties().find(pinEntity => pinEntity.PinName.toString() == "Value")?.DefaultValue]
case Configuration.paths.materialExpressionConstant2Vector:
input ??= [
value ??= [
entity.getCustomproperties().find(pinEntity => pinEntity.PinName?.toString() == "X")?.DefaultValue,
entity.getCustomproperties().find(pinEntity => pinEntity.PinName?.toString() == "Y")?.DefaultValue,
]
case Configuration.paths.materialExpressionConstant3Vector:
case Configuration.paths.materialExpressionConstant4Vector:
if (!input) {
if (!value) {
const vector = entity.getCustomproperties()
.find(pinEntity => pinEntity.PinName?.toString() == "Constant")
?.DefaultValue
input = vector instanceof VectorEntity ? [vector.X, vector.Y, vector.Z].map(v => v.valueOf())
value = 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)).join(",")
if (value?.length > 0) {
return value.map(v => Utility.printExponential(v)).join(",")
}
value = undefined
break
case Configuration.paths.materialExpressionFunctionInput: {
const materialObject = entity.getMaterialSubobject()

View File

@@ -56,7 +56,7 @@ const pinColorMaterial = css`120, 120, 120`
/** @param {PinEntity<IEntity>} entity */
export default function pinColor(entity) {
if (entity.PinType.PinCategory?.toString() === "mask") {
const result = colors[entity.PinType.PinSubCategory]
const result = colors[entity.PinType.PinSubCategory?.toString()]
if (result) {
return result
}

View File

@@ -100,7 +100,7 @@ export default class NodeElement extends ISelectableDraggableElement {
}
/** @param {String} name */
#redirectLinksAfterRename(name) {
#redirectLinksBeforeRename(name) {
for (let sourcePinElement of this.getPinElements()) {
for (let targetPinReference of sourcePinElement.getLinks()) {
this.blueprint.getPin(targetPinReference).redirectLink(
@@ -135,9 +135,9 @@ export default class NodeElement extends ISelectableDraggableElement {
"Name",
/** @param {InstanceType<typeof ObjectEntity.attributes.Name>} newName */
newName => {
this.#redirectLinksBeforeRename(newName.value)
this.nodeTitle = newName.value
this.nodeDisplayName = nodeTitle(entity)
this.#redirectLinksAfterRename(newName.value)
}
)
}

View File

@@ -23,7 +23,7 @@ export default class PinElement extends IElement {
fromAttribute: (value, type) => value
? GuidEntity.grammar.parse(value)
: null,
toAttribute: (value, type) => /** @type {String} */(value?.toString()),
toAttribute: (value, type) => value?.toString(),
},
attribute: "data-id",
reflect: true,
@@ -95,6 +95,7 @@ export default class PinElement extends IElement {
this.isLinked = false
this.connectable = !entity.bNotConnectable?.valueOf()
super.initialize(entity, template)
this.pinId = this.entity.PinId
this.pinType = this.entity.getType()
this.defaultValue = this.entity.getDefaultValue()
this.color = PinElement.properties.color.converter.fromAttribute(this.getColor().toString())
@@ -233,7 +234,7 @@ export default class PinElement extends IElement {
&& pinReference.pinGuid.toString() == originalPinElement.entity.PinId.toString()
)
if (index >= 0) {
this.entity.LinkedTo[index] = newReference
this.entity.LinkedTo.valueOf()[index] = newReference
return true
}
return false

View File

@@ -15,7 +15,7 @@ export default class BlueprintEntity extends ObjectEntity {
/** @param {ObjectEntity} entity */
getHomonymObjectEntity(entity) {
const name = entity.getObjectName(false)
const name = entity.getObjectName()
return this.#objectEntities.find(entity => entity.getObjectName() == name)
}

View File

@@ -61,6 +61,14 @@ export default class IEntity {
this.#ignored = value
}
#inlined = /** @type {typeof IEntity} */(this.constructor).inlined
get inlined() {
return this.#inlined
}
set inlined(value) {
this.#inlined = value
}
#quoted
get quoted() {
return this.#quoted ?? /** @type {typeof IEntity} */(this.constructor).quoted ?? false
@@ -331,7 +339,7 @@ export default class IEntity {
if (keyValue.length && (Self.attributes[key]?.quoted || value.quoted)) {
keyValue = `"${keyValue}"`
}
if (valueType.inlined) {
if (value.inlined) {
const inlinedPrintKey = valueType.className() === "ArrayEntity"
? k => printKey(`${keyValue}${k}`)
: k => printKey(`${keyValue}.${k}`)

View File

@@ -89,11 +89,11 @@ export default class PinEntity extends IEntity {
AutogeneratedDefaultValue: StringEntity,
DefaultObject: ObjectReferenceEntity,
PersistentGuid: GuidEntity,
bHidden: BooleanEntity.withDefault(),
bNotConnectable: BooleanEntity.withDefault(),
bDefaultValueIsReadOnly: BooleanEntity.withDefault(),
bDefaultValueIsIgnored: BooleanEntity.withDefault(),
bAdvancedView: BooleanEntity.withDefault(),
bHidden: BooleanEntity,
bNotConnectable: BooleanEntity,
bDefaultValueIsReadOnly: BooleanEntity,
bDefaultValueIsIgnored: BooleanEntity,
bAdvancedView: BooleanEntity,
bOrphanedPin: BooleanEntity,
}
static grammar = this.createGrammar()

View File

@@ -12,7 +12,7 @@ export default class PinTypeEntity extends IEntity {
static attributes = {
...super.attributes,
PinCategory: StringEntity.withDefault(),
PinSubCategory: StringEntity.withDefault(),
PinSubCategory: StringEntity,
PinSubCategoryObject: ObjectReferenceEntity,
PinSubCategoryMemberReference: FunctionReferenceEntity,
ContainerType: SymbolEntity,

View File

@@ -1,15 +1,22 @@
import P from "parsernostrum"
import Grammar from "../serialization/Grammar.js"
import GuidEntity from "./GuidEntity.js"
import PinEntity from "./PinEntity.js"
export default class UnknownPinEntity extends PinEntity {
static attributes = {
...super.attributes,
PinId: GuidEntity
}
static grammar = this.createGrammar()
/** @returns {P<UnknownPinEntity>} */
static createGrammar() {
return P.seq(
P.reg(new RegExp(`(${Grammar.Regex.Symbol.source})\\s*\\(\\s*`), 1),
// Lookbehind
P.reg(new RegExp(`(${Grammar.Regex.Symbol.source}\\s*)\\(\\s*`), 1),
Grammar.createAttributeGrammar(this).sepBy(Grammar.commaSeparation),
P.reg(/\s*(?:,\s*)?\)/)
).map(([lookbehind, attributes, _2]) => {

View File

@@ -107,9 +107,17 @@ export default class Grammar {
const attributeKey = attributeName.split(Configuration.keysSeparator)
const attributeValue = this.getAttribute(entityType, attributeKey)
const grammar = attributeValue ? attributeValue.grammar : IEntity.unknownEntityGrammar
const inlined = attributeKey.length > 1
return grammar.map(attributeValue =>
values => {
Utility.objectSet(values, attributeKey, attributeValue)
attributeKey.reduce(
(acc, cur, i) => {
acc[cur]["inlined"] = inlined && i < attributeKey.length - 1
return acc[cur]
},
values
)
handleObjectSet(values, attributeKey, attributeValue)
}
)

View File

@@ -7,6 +7,7 @@ import NodeTemplate from "./NodeTemplate.js"
export default class EventNodeTemplate extends NodeTemplate {
static nodeStyleClasses = [...super.nodeStyleClasses, "ueb-node-style-event"]
#delegatePinElement
/** @param {PropertyValues} changedProperties */
firstUpdated(changedProperties) {
@@ -38,21 +39,31 @@ export default class EventNodeTemplate extends NodeTemplate {
`
}
getPinElements() {
return this.element.getPinElements().filter(v => v.entity.PinType.PinCategory?.toString() !== "delegate")
}
createDelegatePinElement() {
const pin = /** @type {PinElementConstructor} */(ElementFactory.getConstructor("ueb-pin")).newObject(
this.element.getPinEntities().find(v => !v.isHidden() && v.PinType.PinCategory?.toString() === "delegate"),
new MinimalPinTemplate(),
this.element
)
pin.template.isNameRendered = false
return pin
if (!this.#delegatePinElement) {
this.#delegatePinElement = /** @type {PinElementConstructor} */(ElementFactory.getConstructor("ueb-pin"))
.newObject(
this.element.getPinEntities().find(v => !v.isHidden() && v.PinType.PinCategory?.toString() === "delegate"),
new MinimalPinTemplate(),
this.element
)
this.#delegatePinElement.template.isNameRendered = false
}
return this.#delegatePinElement
}
createPinElements() {
return this.element.getPinEntities()
.filter(v => !v.isHidden() && v.PinType.PinCategory?.toString() !== "delegate")
.map(pinEntity => /** @type {PinElementConstructor} */(ElementFactory.getConstructor("ueb-pin"))
.newObject(pinEntity, undefined, this.element)
)
return [
this.createDelegatePinElement(),
...this.element.getPinEntities()
.filter(v => !v.isHidden() && v.PinType.PinCategory?.toString() !== "delegate")
.map(pinEntity => /** @type {PinElementConstructor} */(ElementFactory.getConstructor("ueb-pin"))
.newObject(pinEntity, undefined, this.element)
)
]
}
}

View File

@@ -54,17 +54,9 @@ export default class KnotNodeTemplate extends NodeTemplate {
}
setupPins() {
this.element.getPinElements().forEach(
p => /** @type {HTMLElement} */(this.element.querySelector(".ueb-node-border")).appendChild(p)
)
}
/**
* @param {NodeElement} node
* @returns {NodeListOf<PinElement>}
*/
getPinElements(node) {
return node.querySelectorAll("ueb-pin")
for (const p of this.getPinElements()) {
/** @type {HTMLElement} */(this.element.querySelector(".ueb-node-border")).appendChild(p)
}
}
createPinElements() {

View File

@@ -1,7 +1,7 @@
import { html, nothing } from "lit"
import SVGIcon from "../../SVGIcon.js"
import Utility from "../../Utility.js"
import nodeSubtitle from "../../decoding/nodeSubtitle.js"
import ElementFactory from "../../element/ElementFactory.js"
import SVGIcon from "../../SVGIcon.js"
import ISelectableDraggableTemplate from "../ISelectableDraggableTemplate.js"
/** @extends {ISelectableDraggableTemplate<NodeElement>} */
@@ -9,7 +9,7 @@ export default class NodeTemplate extends ISelectableDraggableTemplate {
static nodeStyleClasses = ["ueb-node-style-default"]
#hasSubtitle = false
#subtitle
/** @type {() => PinEntity<IEntity>} */
pinInserter
@@ -55,6 +55,7 @@ export default class NodeTemplate extends ISelectableDraggableTemplate {
/** @param {NodeElement} element */
initialize(element) {
super.initialize(element)
this.#subtitle = nodeSubtitle(element.entity)
this.element.classList.add(.../** @type {typeof NodeTemplate} */(this.constructor).nodeStyleClasses)
this.element.style.setProperty("--ueb-node-color", this.getColor().cssText)
this.pinInserter = this.element.entity.additionalPinInserter()
@@ -113,10 +114,8 @@ export default class NodeTemplate extends ISelectableDraggableTemplate {
${name ? html`
<div class="ueb-node-name-text ueb-ellipsis-nowrap-text">
${name}
${this.#hasSubtitle && this.getTargetType().length > 0 ? html`
<div class="ueb-node-subtitle-text ueb-ellipsis-nowrap-text">
Target is ${Utility.formatStringName(this.getTargetType())}
</div>
${this.#subtitle ? html`
<div class="ueb-node-subtitle-text ueb-ellipsis-nowrap-text">${this.#subtitle}</div>
`: nothing}
</div>
` : nothing}
@@ -137,7 +136,7 @@ export default class NodeTemplate extends ISelectableDraggableTemplate {
this.element.nodeNameElement = /** @type {HTMLElement} */(this.element.querySelector(".ueb-node-name-text"))
let hasInput = false
let hasOutput = false
for (const p of this.element.getPinElements()) {
for (const p of this.getPinElements()) {
if (p === this.defaultPin) {
continue
}
@@ -160,26 +159,14 @@ export default class NodeTemplate extends ISelectableDraggableTemplate {
}
}
getPinElements() {
return this.element.getPinElements()
}
createPinElements() {
return this.element.getPinEntities()
.filter(v => !v.isHidden())
.map(pinEntity => {
this.#hasSubtitle = this.#hasSubtitle
|| pinEntity.PinName.toString() === "self" && pinEntity.pinTitle() === "Target"
return this.createPinElement(pinEntity)
})
}
getTargetType() {
return this.element.entity.FunctionReference?.MemberParent?.getName() ?? "Untitled"
}
/**
* @param {NodeElement} node
* @returns {NodeListOf<PinElement>}
*/
getPinElements(node) {
return node.querySelectorAll("ueb-pin")
.map(pinEntity => this.createPinElement(pinEntity))
}
linksChanged() { }

View File

@@ -110,12 +110,12 @@ export default class PinTemplate extends ITemplate {
return SVGIcon.pcgStackPin
}
}
switch (this.element.entity.PinType?.ContainerType?.serialize()) {
switch (this.element.entity.PinType.ContainerType?.toString()) {
case "Array": return SVGIcon.arrayPin
case "Set": return SVGIcon.setPin
case "Map": return SVGIcon.mapPin
}
if (this.element.entity.PinType?.PinCategory?.toString().toLocaleLowerCase() === "delegate") {
if (this.element.entity.PinType.PinCategory?.toString().toLocaleLowerCase() === "delegate") {
return SVGIcon.delegate
}
if (this.element.nodeElement?.template instanceof VariableOperationNodeTemplate) {

View File

@@ -85,11 +85,6 @@ ueb-pin[data-connectable="false"] .ueb-pin-icon {
visibility: hidden;
}
.ueb-node-style-event ueb-pin[data-type="delegate"] .ueb-pin-icon {
width: 11px;
height: 11px;
}
.ueb-node-inputs .ueb-pin-icon {
margin-right: 6px;
}

53
tests/issues.spec.js Normal file
View File

@@ -0,0 +1,53 @@
import { expect, test } from "./fixtures/test.js"
test.beforeEach(async ({ blueprintPage }) => {
await blueprintPage.removeNodes()
})
test("Issue 27", async ({ blueprintPage }) => {
await blueprintPage.paste(String.raw`
Begin Object Class=/Script/BlueprintGraph.K2Node_CustomEvent Name="K2Node_CustomEvent_0" ExportPath="/Script/BlueprintGraph.K2Node_CustomEvent'/Game/Examples/BallShooter/Blueprints/BallShooterEnvironment.BallShooterEnvironment:EventGraph.K2Node_CustomEvent_0'"
CustomFunctionName="CustomEvent"
NodePosX=1984
NodePosY=1600
ErrorType=3
NodeGuid=8955D806490FF62840F229BD64AC0F8B
CustomProperties Pin (PinId=DA10B1984E92B126FB09CE9D0F767D2E,PinName="OutputDelegate",Direction="EGPD_Output",PinType.PinCategory="delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent="/Script/Engine.BlueprintGeneratedClass'/Game/Examples/BallShooter/Blueprints/BallShooterEnvironment.BallShooterEnvironment_C'",MemberName="CustomEvent",MemberGuid=8955D806490FF62840F229BD64AC0F8B),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_Knot_7 6014BE7344D4B71DCD1CC39ACD1DB9EE,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=A52A36F047563A99081BB3ADC0C688CB,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",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=E88FACB54D1595FDCF2A0BAABA7969CE,PinName="Actor",Direction="EGPD_Output",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.Actor'",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=8183CC924CB230BE8E6DE1963A4145BE,PinName="EndPlayReason",Direction="EGPD_Output",PinType.PinCategory="byte",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Enum'/Script/Engine.EEndPlayReason'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="Destroyed",AutogeneratedDefaultValue="Destroyed",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties UserDefinedPin (PinName="Actor",PinType=(PinCategory="object",PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.Actor'"),DesiredPinDirection=EGPD_Output)
CustomProperties UserDefinedPin (PinName="EndPlayReason",PinType=(PinCategory="byte",PinSubCategoryObject="/Script/CoreUObject.Enum'/Script/Engine.EEndPlayReason'"),DesiredPinDirection=EGPD_Output,PinDefaultValue="Destroyed")
End Object
Begin Object Class=/Script/BlueprintGraph.K2Node_AssignDelegate Name="K2Node_AssignDelegate_0" ExportPath="/Script/BlueprintGraph.K2Node_AssignDelegate'/Game/Examples/BallShooter/Blueprints/BallShooterEnvironment.BallShooterEnvironment:EventGraph.K2Node_AssignDelegate_0'"
DelegateReference=(MemberParent="/Script/CoreUObject.Class'/Script/Engine.Actor'",MemberName="OnEndPlay")
NodePosX=2240
NodePosY=1584
NodeGuid=AD2E460940AE6B07C5FE518E111B2909
CustomProperties Pin (PinId=86FA158D4EBB8E99A0063BBFB5CAFA7D,PinName="execute",PinType.PinCategory="exec",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=98DFCE7B49E479343BD765BE8D9CF13A,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",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=9EEC18F94EE45E5F2DEBCC950A1059E7,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "BaseMCDelegateSelfPinName", "Target"),PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.Actor'",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=3C0089524CDDA9E63853BEA28156FACD,PinName="Delegate",PinFriendlyName=NSLOCTEXT("K2Node", "PinFriendlyDelegatetName", "Event"),PinType.PinCategory="delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent="/Script/CoreUObject.Package'/Script/Engine'",MemberName="ActorEndPlaySignature__DelegateSignature"),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=True,PinType.bIsConst=True,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_Knot_7 424DC49B456B27D825A8F690E6CAA096,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
Begin Object Class=/Script/BlueprintGraph.K2Node_Knot Name="K2Node_Knot_7" ExportPath="/Script/BlueprintGraph.K2Node_Knot'/Game/Examples/BallShooter/Blueprints/BallShooterEnvironment.BallShooterEnvironment:EventGraph.K2Node_Knot_7'"
NodePosX=2160
NodePosY=1648
NodeGuid=A98222664329B5AA6D32FCBFC43C062C
CustomProperties Pin (PinId=6014BE7344D4B71DCD1CC39ACD1DB9EE,PinName="InputPin",PinType.PinCategory="delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent="/Script/Engine.BlueprintGeneratedClass'/Game/Examples/BallShooter/Blueprints/BallShooterEnvironment.BallShooterEnvironment_C'",MemberName="CustomEvent",MemberGuid=8955D806490FF62840F229BD64AC0F8B),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CustomEvent_0 DA10B1984E92B126FB09CE9D0F767D2E,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=True,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=424DC49B456B27D825A8F690E6CAA096,PinName="OutputPin",Direction="EGPD_Output",PinType.PinCategory="delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent="/Script/Engine.BlueprintGeneratedClass'/Game/Examples/BallShooter/Blueprints/BallShooterEnvironment.BallShooterEnvironment_C'",MemberName="CustomEvent",MemberGuid=8955D806490FF62840F229BD64AC0F8B),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_AssignDelegate_0 3C0089524CDDA9E63853BEA28156FACD,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
`)
const eventNode = await blueprintPage.blueprintLocator.locator("ueb-node").nth(0)
const knotNode = await blueprintPage.blueprintLocator.locator("ueb-node").nth(2)
const assignNode = await blueprintPage.blueprintLocator.locator("ueb-node").nth(1)
const pin1 = eventNode.locator("ueb-pin").nth(0)
const pin2A = knotNode.locator("ueb-pin").nth(0)
const pin2B = knotNode.locator("ueb-pin").nth(1)
const pin3 = assignNode.locator("ueb-pin").nth(2)
expect(await pin1.evaluate(/** @param {PinElement} pin */ pin => pin.isLinked)).toBeTruthy()
expect(await pin2A.evaluate(/** @param {PinElement} pin */ pin => pin.isLinked)).toBeTruthy()
expect(await pin2B.evaluate(/** @param {PinElement} pin */ pin => pin.isLinked)).toBeTruthy()
expect(await pin3.evaluate(/** @param {PinElement} pin */ pin => pin.isLinked)).toBeTruthy()
expect(await blueprintPage.blueprintLocator.locator("ueb-link")).toHaveCount(2)
})

View File

@@ -81,9 +81,116 @@ export default class EventNodes extends NodeTests {
color: Configuration.nodeColors.blue,
icon: SVGIcon.node,
pins: 3,
pinNames: [
"Target",
],
pinNames: ["Target"],
delegate: false,
development: false,
},
{
name: "Bind Event to On Actor Hit",
value: String.raw`
Begin Object Class=/Script/BlueprintGraph.K2Node_AddDelegate Name="K2Node_AddDelegate_0" ExportPath="/Script/BlueprintGraph.K2Node_AddDelegate'/Game/Examples/MazeSolver/Blueprints/MazeSolverTrainer.MazeSolverTrainer:EventGraph.K2Node_AddDelegate_0'"
DelegateReference=(MemberParent="/Script/CoreUObject.Class'/Script/Engine.Actor'",MemberName="OnActorHit")
NodePosX=256
NodePosY=-48
NodeGuid=A94C879148610E75EBAC94807E94F5DD
CustomProperties Pin (PinId=252C72EA45F1370E8B00FFB6D5C87B3A,PinName="execute",PinType.PinCategory="exec",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=(K2Node_Event_0 F135CD17D40347269BBBD101437B6AF0,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=66AE85F346F350F62B127B97DFC49563,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",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=D7358C004BE0EF6651DE69A7346E77D4,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "BaseMCDelegateSelfPinName", "Target"),PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.Actor'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_0 EDE2516A4F187C93CBF2D7AE88066240,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=180DE95D4FD5AF2404F1CB80F0FBD29E,PinName="Delegate",PinFriendlyName=NSLOCTEXT("K2Node", "PinFriendlyDelegatetName", "Event"),PinType.PinCategory="Delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent="/Script/CoreUObject.Package'/Script/Engine'",MemberName="ActorHitSignature__DelegateSignature"),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=True,PinType.bIsConst=True,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
`,
size: [13.5, 8],
color: Configuration.nodeColors.blue,
icon: SVGIcon.node,
pins: 4,
pinNames: ["Target", "Event"],
delegate: false,
development: false,
},
{
name: "Bind Event to Modified Event Dynamic",
value: String.raw`
Begin Object Class=/Script/BlueprintGraph.K2Node_AddDelegate Name="K2Node_AddDelegate_1" ExportPath="/Script/BlueprintGraph.K2Node_AddDelegate'/Engine/Maps/Templates/NewWorld.NewWorld:PersistentLevel.NewWorld.EventGraph.K2Node_AddDelegate_1'"
DelegateReference=(MemberParent="/Script/CoreUObject.Class'/Script/Engine.AnimDataModel'",MemberName="ModifiedEventDynamic")
NodePosX=1920
NodePosY=-384
NodeGuid=9F798056B9CB474A9EE2FE88063D4D20
CustomProperties Pin (PinId=4D2AF198B99A445C925AA2A8380C533E,PinName="execute",PinType.PinCategory="exec",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=46363EE0231F4EA186E029977F586416,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",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=D3AD4B9A6EA745BD8EC70EE4B33FDB44,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "BaseMCDelegateSelfPinName", "Target"),PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.AnimDataModel'",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=48F1FF2C45A147C7B390B9D1A35FC3A2,PinName="Delegate",PinFriendlyName=NSLOCTEXT("K2Node", "PinFriendlyDelegatetName", "Event"),PinType.PinCategory="delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent="/Script/CoreUObject.Package'/Script/Engine'",MemberName="AnimDataModelModifiedDynamicEvent__DelegateSignature"),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=True,PinType.bIsConst=True,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
`,
size: [18, 8],
color: Configuration.nodeColors.blue,
icon: SVGIcon.node,
pins: 4,
pinNames: ["Target", "Event"],
delegate: false,
development: false,
},
{
name: "Unbind all Events from On Scroll Bar Visibility Changed",
value: String.raw`
Begin Object Class=/Script/BlueprintGraph.K2Node_ClearDelegate Name="K2Node_ClearDelegate_1" ExportPath="/Script/BlueprintGraph.K2Node_ClearDelegate'/Engine/Maps/Templates/NewWorld.NewWorld:PersistentLevel.NewWorld.EventGraph.K2Node_ClearDelegate_1'"
DelegateReference=(MemberParent="/Script/CoreUObject.Class'/Script/UMG.ScrollBox'",MemberName="OnScrollBarVisibilityChanged")
NodePosX=2688
NodePosY=-640
NodeGuid=48B5357C4A6344B685D58484C8CA6100
CustomProperties Pin (PinId=0186059A7F58440D9CDE09CF2E4211BE,PinName="execute",PinType.PinCategory="exec",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=CB57C7A59EC4491EAC932C4AF3B43254,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",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=C088A6049D2C4A238885632C5D33C490,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "BaseMCDelegateSelfPinName", "Target"),PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/UMG.ScrollBox'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
`,
size: [24, 6],
color: Configuration.nodeColors.blue,
icon: SVGIcon.node,
pins: 3,
pinNames: ["Target"],
delegate: false,
development: false,
},
{
name: "Unbind Event from On Pre Initialize",
value: String.raw`
Begin Object Class=/Script/BlueprintGraph.K2Node_RemoveDelegate Name="K2Node_RemoveDelegate_0" ExportPath="/Script/BlueprintGraph.K2Node_RemoveDelegate'/Engine/Maps/Templates/NewWorld.NewWorld:PersistentLevel.NewWorld.EventGraph.K2Node_RemoveDelegate_0'"
DelegateReference=(MemberParent="/Script/CoreUObject.Class'/Script/ControlRig.ControlRigComponent'",MemberName="OnPreInitializeDelegate")
NodePosX=2688
NodePosY=-512
NodeGuid=68504A8520394A2F9B8AACFD2F457D9E
CustomProperties Pin (PinId=1D7D2FBFEB344721B4EE9D149F615BBD,PinName="execute",PinType.PinCategory="exec",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=2AB22AF068E943BEB99DAAE276EA0C9A,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",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=42FC9475607C479097689D14713CCC43,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "BaseMCDelegateSelfPinName", "Target"),PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/ControlRig.ControlRigComponent'",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=7729342B171248D8A6EF908ED8E1D8B7,PinName="Delegate",PinFriendlyName=NSLOCTEXT("K2Node", "PinFriendlyDelegatetName", "Event"),PinType.PinCategory="delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent="/Script/CoreUObject.Package'/Script/ControlRig'",MemberName="ControlRigComponentDelegate__DelegateSignature"),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=True,PinType.bIsConst=True,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
`,
size: [16.5, 8],
color: Configuration.nodeColors.blue,
icon: SVGIcon.node,
pins: 4,
pinNames: ["Target", "Event"],
delegate: false,
development: false,
},
{
name: "Bind Event to On Pre Initialize",
value: String.raw`
Begin Object Class=/Script/BlueprintGraph.K2Node_AddDelegate Name="K2Node_AddDelegate_4" ExportPath="/Script/BlueprintGraph.K2Node_AddDelegate'/Engine/Maps/Templates/NewWorld.NewWorld:PersistentLevel.NewWorld.EventGraph.K2Node_AddDelegate_4'"
DelegateReference=(MemberParent="/Script/CoreUObject.Class'/Script/ControlRig.ControlRigComponent'",MemberName="OnPreInitializeDelegate")
NodePosX=1760
NodePosY=-688
NodeGuid=12A5D8F5736842F7B70C88C26D36B422
CustomProperties Pin (PinId=CF6740C1F0A4487E91E6C33CA32F78B7,PinName="execute",PinType.PinCategory="exec",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=AD533F241A0B44A68FCDFDFE2F698A95,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",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=6E432C9EE60143F4890F0BDC6BCF4637,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "BaseMCDelegateSelfPinName", "Target"),PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/ControlRig.ControlRigComponent'",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=8C762AAFD03F4B89A4150D17A3C20598,PinName="Delegate",PinFriendlyName=NSLOCTEXT("K2Node", "PinFriendlyDelegatetName", "Event"),PinType.PinCategory="delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent="/Script/CoreUObject.Package'/Script/ControlRig'",MemberName="ControlRigComponentDelegate__DelegateSignature"),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=True,PinType.bIsConst=True,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
`,
size: [15, 8],
color: Configuration.nodeColors.blue,
icon: SVGIcon.node,
pins: 4,
pinNames: ["Target", "Event"],
delegate: false,
development: false,
},