Required mark for PCG pins

This commit is contained in:
barsdeveloper
2025-04-03 23:40:52 +03:00
parent 5ef585eb34
commit fb7fc9fc66
12 changed files with 159 additions and 30 deletions

View File

@@ -781,6 +781,19 @@ ueb-blueprint[data-scrolling=false][data-selecting=false] .ueb-pin-wrapper:hover
background: none !important; background: none !important;
} }
.ueb-pin-required-mark {
width: 0;
}
.ueb-pin-required-mark::before {
content: "";
display: block;
width: 6px;
height: 4px;
background: var(--ueb-pin-color);
margin-left: -13px;
border-radius: 0 2px 2px 0;
}
.ueb-pin-content { .ueb-pin-content {
display: flex; display: flex;
align-items: center; align-items: center;

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

33
dist/ueblueprint.js vendored
View File

@@ -5884,13 +5884,9 @@ class PinEntity extends IEntity {
} }
if (this.objectEntity?.isPcg()) { if (this.objectEntity?.isPcg()) {
const pcgSuboject = this.objectEntity.getPcgSubobject(); const pcgSuboject = this.objectEntity.getPcgSubobject();
const pinObjectReference = this.isInput() const pinObject = this.getPinObject(pcgSuboject);
? pcgSuboject.InputPins?.valueOf()[this.pinIndex] if (pinObject) {
: pcgSuboject.OutputPins?.valueOf()[this.pinIndex]; let allowedTypes = pinObject["Properties"]?.AllowedTypes?.toString() ?? "";
if (pinObjectReference) {
/** @type {ObjectEntity} */
const pinObject = pcgSuboject[Configuration.subObjectAttributeNameFromReference(pinObjectReference, true)];
let allowedTypes = pinObject.Properties?.AllowedTypes?.toString() ?? "";
if (allowedTypes == "") { if (allowedTypes == "") {
allowedTypes = this.PinType.PinCategory ?? ""; allowedTypes = this.PinType.PinCategory ?? "";
if (allowedTypes == "") { if (allowedTypes == "") {
@@ -5899,8 +5895,8 @@ class PinEntity extends IEntity {
} }
if (allowedTypes) { if (allowedTypes) {
if ( if (
pinObject.Properties.bAllowMultipleData?.valueOf() !== false pinObject["Properties"].bAllowMultipleData?.valueOf() !== false
&& pinObject.Properties.bAllowMultipleConnections?.valueOf() !== false && pinObject["Properties"].bAllowMultipleConnections?.valueOf() !== false
) { ) {
allowedTypes += "[]"; allowedTypes += "[]";
} }
@@ -6017,6 +6013,17 @@ class PinEntity extends IEntity {
return false return false
} }
/** @param {ObjectEntity} pcgSuboject */
getPinObject(pcgSuboject) {
const pinObjectReference = this.isInput()
? pcgSuboject.InputPins?.valueOf()[this.pinIndex]
: pcgSuboject.OutputPins?.valueOf()[this.pinIndex];
if (pinObjectReference) {
/** @type {ObjectEntity} */
return pcgSuboject[Configuration.subObjectAttributeNameFromReference(pinObjectReference, true)]
}
}
getSubCategory() { getSubCategory() {
return this.PinType.PinSubCategoryObject?.path return this.PinType.PinSubCategoryObject?.path
} }
@@ -9611,8 +9618,12 @@ class PinTemplate extends ITemplate {
${this.isInputRendered() ? this.renderInput() : x``} ${this.isInputRendered() ? this.renderInput() : x``}
</div> </div>
`; `;
let pcgSubobject = this.element.nodeElement.entity.getPcgSubobject();
return x` return x`
<div class="ueb-pin-wrapper"> <div class="ueb-pin-wrapper">
${pcgSubobject && this.element.entity.getPinObject(pcgSubobject)?.["Properties"]?.["PinStatus"] == "Required"
? x`<div class="ueb-pin-required-mark"></div>`
: E}
${this.element.isInput() ? x`${icon}${content}` : x`${content}${icon}`} ${this.element.isInput() ? x`${icon}${content}` : x`${content}${icon}`}
</div> </div>
` `
@@ -9647,13 +9658,13 @@ class PinTemplate extends ITemplate {
case "Set": return SVGIcon.setPin case "Set": return SVGIcon.setPin
case "Map": return SVGIcon.mapPin 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 return SVGIcon.delegate
} }
if (this.element.nodeElement?.template instanceof VariableOperationNodeTemplate) { if (this.element.nodeElement?.template instanceof VariableOperationNodeTemplate) {
return SVGIcon.operationPin return SVGIcon.operationPin
} }
if (this.element.entity.PinType.PinCategory?.toString().toLocaleLowerCase() === "statictype") { if (this.element.entity.PinType.PinCategory?.toString().toLocaleLowerCase() == "statictype") {
return SVGIcon.staticPin return SVGIcon.staticPin
} }
return SVGIcon.genericPin return SVGIcon.genericPin

File diff suppressed because one or more lines are too long

View File

@@ -186,13 +186,9 @@ export default class PinEntity extends IEntity {
} }
if (this.objectEntity?.isPcg()) { if (this.objectEntity?.isPcg()) {
const pcgSuboject = this.objectEntity.getPcgSubobject() const pcgSuboject = this.objectEntity.getPcgSubobject()
const pinObjectReference = this.isInput() const pinObject = this.getPinObject(pcgSuboject)
? pcgSuboject.InputPins?.valueOf()[this.pinIndex] if (pinObject) {
: pcgSuboject.OutputPins?.valueOf()[this.pinIndex] let allowedTypes = pinObject["Properties"]?.AllowedTypes?.toString() ?? ""
if (pinObjectReference) {
/** @type {ObjectEntity} */
const pinObject = pcgSuboject[Configuration.subObjectAttributeNameFromReference(pinObjectReference, true)]
let allowedTypes = pinObject.Properties?.AllowedTypes?.toString() ?? ""
if (allowedTypes == "") { if (allowedTypes == "") {
allowedTypes = this.PinType.PinCategory ?? "" allowedTypes = this.PinType.PinCategory ?? ""
if (allowedTypes == "") { if (allowedTypes == "") {
@@ -201,8 +197,8 @@ export default class PinEntity extends IEntity {
} }
if (allowedTypes) { if (allowedTypes) {
if ( if (
pinObject.Properties.bAllowMultipleData?.valueOf() !== false pinObject["Properties"].bAllowMultipleData?.valueOf() !== false
&& pinObject.Properties.bAllowMultipleConnections?.valueOf() !== false && pinObject["Properties"].bAllowMultipleConnections?.valueOf() !== false
) { ) {
allowedTypes += "[]" allowedTypes += "[]"
} }
@@ -319,6 +315,17 @@ export default class PinEntity extends IEntity {
return false return false
} }
/** @param {ObjectEntity} pcgSuboject */
getPinObject(pcgSuboject) {
const pinObjectReference = this.isInput()
? pcgSuboject.InputPins?.valueOf()[this.pinIndex]
: pcgSuboject.OutputPins?.valueOf()[this.pinIndex]
if (pinObjectReference) {
/** @type {ObjectEntity} */
return pcgSuboject[Configuration.subObjectAttributeNameFromReference(pinObjectReference, true)]
}
}
getSubCategory() { getSubCategory() {
return this.PinType.PinSubCategoryObject?.path return this.PinType.PinSubCategoryObject?.path
} }

View File

@@ -79,8 +79,12 @@ export default class PinTemplate extends ITemplate {
${this.isInputRendered() ? this.renderInput() : html``} ${this.isInputRendered() ? this.renderInput() : html``}
</div> </div>
` `
let pcgSubobject = this.element.nodeElement.entity.getPcgSubobject()
return html` return html`
<div class="ueb-pin-wrapper"> <div class="ueb-pin-wrapper">
${pcgSubobject && this.element.entity.getPinObject(pcgSubobject)?.["Properties"]?.["PinStatus"] == "Required"
? html`<div class="ueb-pin-required-mark"></div>`
: nothing}
${this.element.isInput() ? html`${icon}${content}` : html`${content}${icon}`} ${this.element.isInput() ? html`${icon}${content}` : html`${content}${icon}`}
</div> </div>
` `
@@ -115,13 +119,13 @@ export default class PinTemplate extends ITemplate {
case "Set": return SVGIcon.setPin case "Set": return SVGIcon.setPin
case "Map": return SVGIcon.mapPin 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 return SVGIcon.delegate
} }
if (this.element.nodeElement?.template instanceof VariableOperationNodeTemplate) { if (this.element.nodeElement?.template instanceof VariableOperationNodeTemplate) {
return SVGIcon.operationPin return SVGIcon.operationPin
} }
if (this.element.entity.PinType.PinCategory?.toString().toLocaleLowerCase() === "statictype") { if (this.element.entity.PinType.PinCategory?.toString().toLocaleLowerCase() == "statictype") {
return SVGIcon.staticPin return SVGIcon.staticPin
} }
return SVGIcon.genericPin return SVGIcon.genericPin

View File

@@ -67,6 +67,20 @@ ueb-blueprint[data-scrolling="false"][data-selecting="false"] .ueb-pin-wrapper:h
background: none !important; background: none !important;
} }
.ueb-pin-required-mark {
width: 0;
&::before {
content: "";
display: block;
width: 6px;
height: 4px;
background: var(--ueb-pin-color);
margin-left: -13px;
border-radius: 0 2px 2px 0;
}
}
.ueb-pin-content { .ueb-pin-content {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@@ -1,4 +1,4 @@
import { testNode, expect } from "./fixtures/test.js" import { expect, testNode } from "./fixtures/test.js"
testNode({ testNode({
name: "Conv Transform To String", name: "Conv Transform To String",

80
tests/nodeDataCount.spec.js Executable file
View File

@@ -0,0 +1,80 @@
import Configuration from "../js/Configuration.js"
import { expect, testNode } from "./fixtures/test.js"
testNode({
name: "Data Count",
title: "Data Num",
subtitle: null,
value: String.raw`
Begin Object Class=/Script/PCGEditor.PCGEditorGraphNode Name="PCGEditorGraphNode_2" ExportPath="/Script/PCGEditor.PCGEditorGraphNode'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2'"
Begin Object Class=/Script/PCG.PCGNode Name="DataNum_2" ExportPath="/Script/PCG.PCGNode'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2'"
Begin Object Class=/Script/PCG.PCGTrivialSettings Name="DefaultNodeSettings" Archetype="/Script/PCG.PCGTrivialSettings'/Script/PCG.Default__PCGNode:DefaultNodeSettings'" ExportPath="/Script/PCG.PCGTrivialSettings'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2.DefaultNodeSettings'"
End Object
Begin Object Class=/Script/PCG.PCGDataNumSettings Name="PCGDataNumSettings_0" ExportPath="/Script/PCG.PCGDataNumSettings'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2.PCGDataNumSettings_0'"
End Object
Begin Object Class=/Script/PCG.PCGPin Name="PCGPin_0" ExportPath="/Script/PCG.PCGPin'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2.PCGPin_0'"
End Object
Begin Object Class=/Script/PCG.PCGPin Name="PCGPin_1" ExportPath="/Script/PCG.PCGPin'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2.PCGPin_1'"
End Object
Begin Object Class=/Script/PCG.PCGPin Name="PCGPin_2" ExportPath="/Script/PCG.PCGPin'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2.PCGPin_2'"
End Object
Begin Object Class=/Script/PCG.PCGPin Name="PCGPin_3" ExportPath="/Script/PCG.PCGPin'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2.PCGPin_3'"
End Object
End Object
Begin Object Name="DataNum_2" ExportPath="/Script/PCG.PCGNode'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2'"
Begin Object Name="DefaultNodeSettings" ExportPath="/Script/PCG.PCGTrivialSettings'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2.DefaultNodeSettings'"
End Object
Begin Object Name="PCGDataNumSettings_0" ExportPath="/Script/PCG.PCGDataNumSettings'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2.PCGDataNumSettings_0'"
Seed=45482541
CachedOverridableParams(0)=(Label="OutputAttributeName",PropertiesNames=("OutputAttributeName"),PropertyClass="/Script/CoreUObject.Class'/Script/PCG.PCGDataNumSettings'")
End Object
Begin Object Name="PCGPin_0" ExportPath="/Script/PCG.PCGPin'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2.PCGPin_0'"
Node="/Script/PCG.PCGNode'PCGEditorGraphNode_2.DataNum_2'"
Properties=(Label="In",PinStatus=Required)
End Object
Begin Object Name="PCGPin_1" ExportPath="/Script/PCG.PCGPin'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2.PCGPin_1'"
Node="/Script/PCG.PCGNode'PCGEditorGraphNode_2.DataNum_2'"
Properties=(Label="Overrides",AllowedTypes=Param,PinStatus=OverrideOrUserParam,Tooltip=NSLOCTEXT("PCGSettings", "GlobalParamPinTooltip", "Atribute Set containing multiple parameters to override. Names must match perfectly."))
End Object
Begin Object Name="PCGPin_2" ExportPath="/Script/PCG.PCGPin'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2.PCGPin_2'"
Node="/Script/PCG.PCGNode'PCGEditorGraphNode_2.DataNum_2'"
Properties=(Label="OutputAttributeName",AllowedTypes=Param,bAllowMultipleData=False,PinStatus=OverrideOrUserParam,Tooltip=LOCGEN_FORMAT_ORDERED(NSLOCTEXT("PCGSettings", "OverridableParamPinTooltip", "{0}Attribute type is \"{1}\" and its exact name is \"{2}\""), "", NSLOCTEXT("", "F685A80C7F3642D39D0D096256DA7E07", "FName"), NSLOCTEXT("", "0337A20A0B2C400AAE0AF477C663D73D", "OutputAttributeName")),bAllowMultipleConnections=False)
End Object
Begin Object Name="PCGPin_3" ExportPath="/Script/PCG.PCGPin'/Game/NewPCGGraph.NewPCGGraph:PCGEditorGraph_0.PCGEditorGraphNode_2.DataNum_2.PCGPin_3'"
Node="/Script/PCG.PCGNode'PCGEditorGraphNode_2.DataNum_2'"
Properties=(Label="Out",AllowedTypes=Param,Tooltip=NSLOCTEXT("PCGDataNumElement", "OutParamTooltip", "Attribute set containing the data count from the input collection"))
End Object
PositionX=560
PositionY=160
SettingsInterface="/Script/PCG.PCGDataNumSettings'PCGDataNumSettings_0'"
InputPins(0)="/Script/PCG.PCGPin'PCGPin_0'"
InputPins(1)="/Script/PCG.PCGPin'PCGPin_1'"
InputPins(2)="/Script/PCG.PCGPin'PCGPin_2'"
OutputPins(0)="/Script/PCG.PCGPin'PCGPin_3'"
End Object
PCGNode="/Script/PCG.PCGNode'DataNum_2'"
NodePosX=560
NodePosY=160
AdvancedPinDisplay=Shown
bUserSetEnabledState=True
bCanRenameNode=False
NodeGuid=7CCECFCAA65840AD93744F46C8689EBB
CustomProperties Pin (PinId=E362D4F678C942C08A861CFE7E8FA846,PinName="In",PinFriendlyName="In",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,)
CustomProperties Pin (PinId=04A829D535AB461AA23D8CA2BB1BF18A,PinName="Overrides",PinFriendlyName="Overrides",PinType.PinCategory="Attribute Set",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=True,bOrphanedPin=False,)
CustomProperties Pin (PinId=6843659B0B194D358888D2F44F517B89,PinName="OutputAttributeName",PinFriendlyName=NSLOCTEXT("UObjectDisplayNames", "PCGDataNumSettings:OutputAttributeName", "Output Attribute Name"),PinType.PinCategory="Attribute Set",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=True,bOrphanedPin=False,)
CustomProperties Pin (PinId=D863A6ECDFA8449787BE6CA83A3B4617,PinName="Out",PinFriendlyName="Out",Direction="EGPD_Output",PinType.PinCategory="Attribute Set",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
`,
size: [14.5, 9],
color: Configuration.nodeColors.blue,
icon: null,
pins: 4,
pinNames: ["In", "Overrides", "Output Attribute Name", "Out"],
delegate: false,
development: false,
additionalTest: async (node, pins) => {
for (let i = 0; i < pins.length; ++i) {
await expect(pins[i].locator(".ueb-pin-required-mark")).toHaveCount(i == 0 ? 1 : 0)
}
}
})

View File

@@ -1,6 +1,6 @@
import Configuration from "../js/Configuration.js" import Configuration from "../js/Configuration.js"
import SVGIcon from "../js/SVGIcon.js" import SVGIcon from "../js/SVGIcon.js"
import { testNode, expect } from "./fixtures/test.js" import { expect, testNode } from "./fixtures/test.js"
testNode({ testNode({
name: "Print String", name: "Print String",