Various fixes, tests and refactoring

This commit is contained in:
barsdeveloper
2023-01-17 22:22:25 +01:00
parent bb84b31b07
commit 47106f748d
26 changed files with 580 additions and 234 deletions

View File

@@ -53,6 +53,38 @@ describe("Entity initialization", () => {
.which.is.instanceOf(Set)
.and.is.deep.equal(new Set([10, 20, 30, 40, 50, 60, 70]))
)
it("is equal to another empty SimpleEntity", () => expect(entity.equals(new SimpleEntity()))
.to.be.true
)
const other = new SimpleEntity({
someString2: "gamma"
})
it("is not equal to another empty SimpleEntity", () => expect(entity.equals(other))
.to.be.false
)
const other1 = new SimpleEntity({
someNumber: 123,
someString: "a",
someString2: "b",
someBoolean: false,
someBoolean2: false,
someObjectString: new String("delta"),
someArray: [-1, -2, -3],
someSet: new Set([-10, -20, -30]),
})
const other2 = new SimpleEntity({
someNumber: 123,
someString: "a",
someString2: "b",
someBoolean: false,
someBoolean2: false,
someObjectString: "delta",
someArray: [-1, -2, -3],
someSet: new Set([-10, -20, -30]),
})
it("compares equal entities as equal", () => expect(other1.equals(other2))
.to.be.true
)
})
context("ComplexEntity", () => {

View File

@@ -1,5 +1,6 @@
/// <reference types="cypress" />
import IEntity from "../../js/entity/IEntity"
import Utility from "../../js/Utility"
describe("Utility class", () => {
@@ -68,6 +69,34 @@ describe("Utility class", () => {
[-2, "Alpha", new String("beta"), new Number(40), [1, 2, 3]],
[new Number(-2), new String("alpha"), new String("beta"), new Number(40), new Array(1, 2, 3)]
)).to.be.false // Second element is different
expect(Utility.equals(
new Set(["alpha", -67, new String("beta"), [1, 2, 3]]),
new Set([-67, "beta", new String("alpha"), [1, 2, 3]])
)).to.be.true
expect(Utility.equals( // First element has capital Beta
new Set(["alpha", -67, new String("Beta"), [1, 2, 3]]),
new Set([-67, "beta", new String("alpha"), [1, 2, 3]])
)).to.be.false
expect(Utility.equals( // First element has capital Beta
new Set(["alpha", -67, new String("beta"), [1, 2, 3]]),
new Set([-67, "beta", new String("alpha"), [1, 3]])
)).to.be.false
expect(Utility.equals( // Different number of elements
new Set([2, 4, 6, 8]),
new Set([8, 6, 4])
)).to.be.false
expect(Utility.equals( // Second element has different type
new Set([4, "6", 8]),
new Set([8, 6, 4])
)).to.be.false
expect(Utility.equals(
new Set([new IEntity({ a: "alpha", b: new String("beta") })]),
new Set([new IEntity({ a: "alpha", b: new String("beta") })]),
)).to.be.true
expect(Utility.equals( // First a key has a number
new Set([new IEntity({ a: 2, b: new String("beta") })]),
new Set([new IEntity({ a: "alpha", b: new String("beta") })]),
)).to.be.false
})
it("isValueOfType method test", () => {
expect(Utility.isValueOfType(34, Number)).to.be.true

View File

@@ -187,7 +187,6 @@ ueb-link {
* their hover behavior correctly firing.
*/
visibility: hidden;
z-index: 2;
}
ueb-link > svg {
@@ -609,8 +608,8 @@ ueb-blueprint[data-scrolling=false][data-selecting=false] .ueb-pin-wrapper:hover
.ueb-pin-icon {
color: var(--ueb-pin-color);
width: 13px;
height: 13px;
width: 12px;
height: 12px;
text-align: left;
}
@@ -626,11 +625,10 @@ ueb-blueprint[data-scrolling=false][data-selecting=false] .ueb-pin-wrapper:hover
vertical-align: top;
}
ueb-pin[data-type=exec] .ueb-pin-icon > svg {
--ueb-pin-color: white;
ueb-pin[data-type=exec] .ueb-pin-icon {
width: 15px;
height: 15px;
vertical-align: middle;
--ueb-pin-color: white;
}
ueb-pin[data-linked=true] .ueb-pin-tofill {

View File

@@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../../scss/style.scss","../../scss/ueb-knot.scss","../../scss/ueb-link.scss","../../scss/ueb-node.scss","../../scss/ueb-pin.scss","../../scss/ueb-ui-controls.scss","../../scss/ueb-window.scss"],"names":[],"mappings":"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","file":"ueb-style.css"}
{"version":3,"sourceRoot":"","sources":["../../scss/style.scss","../../scss/ueb-knot.scss","../../scss/ueb-link.scss","../../scss/ueb-node.scss","../../scss/ueb-pin.scss","../../scss/ueb-ui-controls.scss","../../scss/ueb-window.scss"],"names":[],"mappings":"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","file":"ueb-style.css"}

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../../scss/style.scss","../../scss/ueb-knot.scss","../../scss/ueb-link.scss","../../scss/ueb-node.scss","../../scss/ueb-pin.scss","../../scss/ueb-ui-controls.scss","../../scss/ueb-window.scss"],"names":[],"mappings":"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","file":"ueb-style.min.css"}
{"version":3,"sourceRoot":"","sources":["../../scss/style.scss","../../scss/ueb-knot.scss","../../scss/ueb-link.scss","../../scss/ueb-node.scss","../../scss/ueb-pin.scss","../../scss/ueb-ui-controls.scss","../../scss/ueb-window.scss"],"names":[],"mappings":"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","file":"ueb-style.min.css"}

377
dist/ueblueprint.js vendored
View File

@@ -461,6 +461,10 @@ class Utility {
* @param {AnyValue} b
*/
static equals(a, b) {
// Here we cannot check both instanceof IEntity because this would introduce a circular include dependency
if (/** @type {IEntity?} */(a)?.equals && /** @type {IEntity?} */(b)?.equals) {
return /** @type {IEntity} */(a).equals(/** @type {IEntity} */(b))
}
a = Utility.sanitize(a);
b = Utility.sanitize(b);
if (a?.constructor === BigInt && b?.constructor === Number) {
@@ -472,7 +476,15 @@ class Utility {
return true
}
if (a instanceof Array && b instanceof Array) {
return a.length == b.length && !a.find((value, i) => !Utility.equals(value, b[i]))
return a.length === b.length && a.every((value, i) => Utility.equals(value, b[i]))
}
if (a instanceof Set && b instanceof Set) {
if (a.size !== b.size) {
return false
}
a = [...a];
b = [...b];
return a.every(first => /** @type {Array} */(b).some(second => Utility.equals(first, second)))
}
return false
}
@@ -486,7 +498,6 @@ class Utility {
return null
}
if (value?.constructor === Object && value?.type instanceof Function) {
// @ts-expect-error
return value.type
}
return /** @type {AnyValueConstructor} */(value?.constructor)
@@ -722,6 +733,7 @@ class Configuration {
"class": i$3`88, 0, 186`,
"default": i$3`255, 255, 255`,
"delegate": i$3`255, 56, 56`,
"enum": i$3`0, 109, 99`,
"exec": i$3`240, 240, 240`,
"int": i$3`31, 224, 172`,
"int64": i$3`169, 223, 172`,
@@ -780,7 +792,6 @@ class Configuration {
static maxZoom = 7
static minZoom = -12
static mouseWheelFactor = 0.2
static nodeDeleteEventName = "ueb-node-delete"
static nodeDragGeneralEventName = "ueb-node-drag-general"
static nodeDragEventName = "ueb-node-drag"
/** @param {NodeElement} node */
@@ -825,8 +836,9 @@ class Configuration {
case Configuration.nodeType.makeMap:
case Configuration.nodeType.select:
return pureFunctionColor
case Configuration.nodeType.macro:
case Configuration.nodeType.executionSequence:
case Configuration.nodeType.ifThenElse:
case Configuration.nodeType.macro:
return i$3`150,150,150`
case Configuration.nodeType.dynamicCast:
return i$3`46, 104, 106`
@@ -915,6 +927,7 @@ class Configuration {
customEvent: "/Script/BlueprintGraph.K2Node_CustomEvent",
doN: "/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:Do N",
dynamicCast: "/Script/BlueprintGraph.K2Node_DynamicCast",
enum: "/Script/CoreUObject.Enum",
event: "/Script/BlueprintGraph.K2Node_Event",
executionSequence: "/Script/BlueprintGraph.K2Node_ExecutionSequence",
forEachElementInEnum: "/Script/BlueprintGraph.K2Node_ForEachElementInEnum",
@@ -946,6 +959,7 @@ class Configuration {
?? Configuration.#pinColor[pin.entity.PinType.PinCategory]
?? Configuration.#pinColor["default"]
}
static removeEventName = "ueb-element-delete"
static scale = {
[-12]: 0.133333,
[-11]: 0.166666,
@@ -1232,7 +1246,8 @@ class IEntity {
const defineAllAttributes = (target, attributes, values = {}, prefix = "") => {
const valuesNames = Object.keys(values);
const attributesNames = Object.keys(attributes);
for (let attributeName of Utility.mergeArrays(attributesNames, valuesNames)) {
const allAttributesNames = Utility.mergeArrays(attributesNames, valuesNames);
for (let attributeName of allAttributesNames) {
let value = Utility.objectGet(values, [attributeName]);
/** @type {AttributeInformation} */
let attribute = attributes[attributeName];
@@ -1414,6 +1429,23 @@ class IEntity {
return Object.keys(this).length
- Object.keys(/** @type {typeof IEntity} */(this.constructor).attributes).length
}
/** @param {IEntity} other */
equals(other) {
const thisKeys = Object.keys(this);
const otherKeys = Object.keys(this);
if (thisKeys.length != otherKeys.length) {
return false
}
for (const key of thisKeys) {
if (this[key] instanceof IEntity && !this[key].equals(other[key])) {
return false
} else if (!Utility.equals(this[key], other[key])) {
return false
}
}
return true
}
}
class IntegerEntity extends IEntity {
@@ -1463,6 +1495,26 @@ class ByteEntity extends IntegerEntity {
}
}
class SymbolEntity extends IEntity {
static attributes = {
value: "",
}
static {
this.cleanupAttributes(this.attributes);
}
constructor(values) {
super(values);
/** @type {String} */ this.value;
}
}
class EnumEntity extends SymbolEntity {
}
class ObjectReferenceEntity extends IEntity {
static attributes = {
@@ -2176,6 +2228,7 @@ class PinEntity extends IEntity {
"/Script/CoreUObject.Vector2D": Vector2DEntity,
"bool": Boolean,
"byte": ByteEntity,
"enum": EnumEntity,
"exec": String,
"int": IntegerEntity,
"int64": Integer64Entity,
@@ -2299,8 +2352,18 @@ class PinEntity extends IEntity {
}
getType() {
if (this.PinType.PinCategory == "struct" || this.PinType.PinCategory == "object") {
return this.PinType.PinSubCategoryObject.path
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
}
@@ -2373,20 +2436,18 @@ class PinEntity extends IEntity {
* @param {PinEntity} targetPinEntity
*/
linkTo(targetObjectName, targetPinEntity) {
/** @type {PinReferenceEntity[]} */
this.LinkedTo;
const linkFound = this.LinkedTo?.find(pinReferenceEntity => {
return pinReferenceEntity.objectName.toString() == targetObjectName
&& pinReferenceEntity.pinGuid.valueOf() == targetPinEntity.PinId.valueOf()
});
const linkFound = this.LinkedTo?.find(pinReferenceEntity =>
pinReferenceEntity.objectName.toString() == targetObjectName
&& pinReferenceEntity.pinGuid.valueOf() == targetPinEntity.PinId.valueOf()
);
if (!linkFound) {
(this.LinkedTo ?? (this.LinkedTo = [])).push(new PinReferenceEntity({
(this.LinkedTo ??= []).push(new PinReferenceEntity({
objectName: targetObjectName,
pinGuid: targetPinEntity.PinId,
}));
return true
}
return false
return false // It is already linked
}
/**
@@ -2414,22 +2475,6 @@ class PinEntity extends IEntity {
}
}
class SymbolEntity extends IEntity {
static attributes = {
value: "",
}
static {
this.cleanupAttributes(this.attributes);
}
constructor(values) {
super(values);
/** @type {String} */ this.value;
}
}
class VariableReferenceEntity extends IEntity {
static attributes = {
@@ -2715,10 +2760,6 @@ class UnknownKeysEntity extends IEntity {
}
}
class EnumEntity extends ByteEntity {
}
// @ts-nocheck
/**
@@ -2990,7 +3031,10 @@ class Grammar {
PathSymbolOptSpaces = r => P.regex(/[0-9\w]+(?: [0-9\w]+)+|[0-9\w]+/).map(v => new PathSymbolEntity({ value: v }))
/** @param {Grammar} r */
Symbol = r => P.regex(/\w+/).map(v => new SymbolEntity({ value: v }))
Symbol = r => P.regex(/[a-zA-Z_]\w*/).map(v => new SymbolEntity({ value: v }))
/** @param {Grammar} r */
Enum = r => P.regex(/[a-zA-Z_]\w*/).map(v => new EnumEntity({ value: v }))
/** @param {Grammar} r */
ObjectReference = r => P.alt(
@@ -3897,6 +3941,7 @@ class IElement extends s {
if (this.isSetup) {
this.updateComplete.then(() => this.cleanup());
}
this.acknowledgeDelete();
}
createRenderRoot() {
@@ -3959,6 +4004,11 @@ class IElement extends s {
}
}
acknowledgeDelete() {
let deleteEvent = new CustomEvent(Configuration.removeEventName);
this.dispatchEvent(deleteEvent);
}
/** @param {IElement} element */
isSameGraph(element) {
return this.blueprint && this.blueprint == element?.blueprint
@@ -4976,14 +5026,17 @@ class LinkTemplate extends IFromToPositionedTemplate {
const knot = /** @type {NodeElementConstructor} */(ElementFactory.getConstructor("ueb-node"))
.newObject(knotEntity);
knot.setLocation(...this.blueprint.snapToGrid(...location));
const knotTemplate = /** @type {KnotNodeTemplate} */(knot.template);
this.blueprint.addGraphElement(knot); // Important: keep it before changing existing links
const inputPin = this.element.getInputPin();
const outputPin = this.element.getOutputPin();
this.element.sourcePin = null;
this.element.destinationPin = null;
const link = /** @type {LinkElementConstructor} */(ElementFactory.getConstructor("ueb-link"))
.newObject(
/** @type {KnotNodeTemplate} */(knot.template).outputPin,
this.element.destinationPin
);
this.element.destinationPin = /** @type {KnotNodeTemplate} */(knot.template).inputPin;
.newObject(outputPin, knotTemplate.inputPin);
this.blueprint.addGraphElement(link);
this.element.sourcePin = knotTemplate.outputPin;
this.element.destinationPin = inputPin;
}
createInputObjects() {
@@ -5005,19 +5058,21 @@ class LinkTemplate extends IFromToPositionedTemplate {
const sourcePin = this.element.sourcePin;
const destinationPin = this.element.destinationPin;
if (changedProperties.has("fromX") || changedProperties.has("toX")) {
const from = this.element.fromX;
const to = this.element.toX;
const isSourceAKnot = sourcePin?.nodeElement.getType() == Configuration.nodeType.knot;
const isDestinationAKnot = destinationPin?.nodeElement.getType() == Configuration.nodeType.knot;
if (isSourceAKnot && (!destinationPin || isDestinationAKnot)) {
if (sourcePin?.isInput() && this.element.toX > this.element.fromX + Configuration.distanceThreshold) {
if (sourcePin?.isInput() && to > from + Configuration.distanceThreshold) {
this.element.sourcePin = /** @type {KnotNodeTemplate} */(sourcePin.nodeElement.template).outputPin;
} else if (sourcePin?.isOutput() && this.element.toX < this.element.fromX - Configuration.distanceThreshold) {
} else if (sourcePin?.isOutput() && to < from - Configuration.distanceThreshold) {
this.element.sourcePin = /** @type {KnotNodeTemplate} */(sourcePin.nodeElement.template).inputPin;
}
}
if (isDestinationAKnot && (!sourcePin || isSourceAKnot)) {
if (destinationPin?.isInput() && this.element.toX < this.element.fromX + Configuration.distanceThreshold) {
if (destinationPin?.isInput() && to < from - Configuration.distanceThreshold) {
this.element.destinationPin = /** @type {KnotNodeTemplate} */(destinationPin.nodeElement.template).outputPin;
} else if (destinationPin?.isOutput() && this.element.toX > this.element.fromX - Configuration.distanceThreshold) {
} else if (destinationPin?.isOutput() && to > from + Configuration.distanceThreshold) {
this.element.destinationPin = /** @type {KnotNodeTemplate} */(destinationPin.nodeElement.template).inputPin;
}
}
@@ -5204,7 +5259,6 @@ class LinkElement extends IFromToPositionedElement {
this.fromY = this.toY;
}
}
this.#linkPins();
}
/**
@@ -5218,7 +5272,7 @@ class LinkElement extends IFromToPositionedElement {
}
if (getCurrentPin()) {
const nodeElement = getCurrentPin().getNodeElement();
nodeElement.removeEventListener(Configuration.nodeDeleteEventName, this.#nodeDeleteHandler);
nodeElement.removeEventListener(Configuration.removeEventName, this.#nodeDeleteHandler);
nodeElement.removeEventListener(
Configuration.nodeDragEventName,
isDestinationPin ? this.#nodeDragDestinatonHandler : this.#nodeDragSourceHandler
@@ -5234,7 +5288,7 @@ class LinkElement extends IFromToPositionedElement {
: this.#sourcePin = pin;
if (getCurrentPin()) {
const nodeElement = getCurrentPin().getNodeElement();
nodeElement.addEventListener(Configuration.nodeDeleteEventName, this.#nodeDeleteHandler);
nodeElement.addEventListener(Configuration.removeEventName, this.#nodeDeleteHandler);
nodeElement.addEventListener(
Configuration.nodeDragEventName,
isDestinationPin ? this.#nodeDragDestinatonHandler : this.#nodeDragSourceHandler
@@ -5259,8 +5313,8 @@ class LinkElement extends IFromToPositionedElement {
#unlinkPins() {
if (this.sourcePin && this.destinationPin) {
this.sourcePin.unlinkFrom(this.destinationPin);
this.destinationPin.unlinkFrom(this.sourcePin);
this.sourcePin.unlinkFrom(this.destinationPin, false);
this.destinationPin.unlinkFrom(this.sourcePin, false);
}
}
@@ -5272,11 +5326,12 @@ class LinkElement extends IFromToPositionedElement {
}
/** @param {Number[]?} location */
setSourceLocation(location = null) {
setSourceLocation(location = null, canPostpone = true) {
if (location == null) {
const self = this;
if (!this.hasUpdated || !this.sourcePin.hasUpdated) {
Promise.all([this.updateComplete, this.sourcePin.updateComplete]).then(() => self.setSourceLocation());
if (canPostpone && (!this.hasUpdated || !this.sourcePin.hasUpdated)) {
Promise.all([this.updateComplete, this.sourcePin.updateComplete])
.then(() => self.setSourceLocation(null, false));
return
}
location = this.sourcePin.template.getLinkLocation();
@@ -5287,12 +5342,12 @@ class LinkElement extends IFromToPositionedElement {
}
/** @param {Number[]?} location */
setDestinationLocation(location = null) {
setDestinationLocation(location = null, canPostpone = true) {
if (location == null) {
const self = this;
if (!this.hasUpdated || !this.destinationPin.hasUpdated) {
if (canPostpone && (!this.hasUpdated || !this.destinationPin.hasUpdated)) {
Promise.all([this.updateComplete, this.destinationPin.updateComplete])
.then(() => self.setDestinationLocation());
.then(() => self.setDestinationLocation(null, false));
return
}
location = this.destinationPin.template.getLinkLocation();
@@ -5301,6 +5356,36 @@ class LinkElement extends IFromToPositionedElement {
this.toY = location[1];
}
getInputPin() {
if (this.sourcePin?.isInput()) {
return this.sourcePin
}
return this.destinationPin
}
/** @param {PinElement} pin */
setInputPin(pin) {
if (this.sourcePin?.isInput()) {
this.sourcePin = pin;
}
this.destinationPin = pin;
}
getOutputPin() {
if (this.destinationPin?.isOutput()) {
return this.destinationPin
}
return this.sourcePin
}
/** @param {PinElement} pin */
setOutputPin(pin) {
if (this.destinationPin?.isOutput()) {
this.destinationPin = pin;
}
this.sourcePin = pin;
}
startDragging() {
this.dragging = true;
}
@@ -5344,6 +5429,11 @@ class LinkElement extends IFromToPositionedElement {
this.linkMessageText = y`Replace existing input connections.`;
}
setMessageReplaceOutputLink() {
this.linkMessageIcon = SVGIcon.correct;
this.linkMessageText = y`Replace existing output connections.`;
}
setMessageSameNode() {
this.linkMessageIcon = SVGIcon.reject;
this.linkMessageText = y`Both are on the same node.`;
@@ -6021,6 +6111,7 @@ class CommentNodeTemplate extends IResizeableTemplate {
* @typedef {import("../../element/LinkElement").LinkElementConstructor} LinkElementConstructor
* @typedef {import("../../element/PinElement").default} PinElement
* @typedef {import("../../template/node/KnotNodeTemplate").default} KnotNodeTemplate
* @typedef {import("../../template/pin/KnotPinTemplate").default} KnotPinTemplate
*/
/** @extends IMouseClickDrag<PinElement> */
@@ -6032,46 +6123,46 @@ class MouseCreateLink extends IMouseClickDrag {
/** @type {PinElement} */
#knotPin = null
#mouseenterHandler =
/** @param {MouseEvent} e */
e => {
if (!this.enteredPin) {
this.linkValid = false;
this.enteredPin = /** @type {PinElement} */(e.target);
const a = this.link.sourcePin ?? this.target; // Remember target might have change
const b = this.enteredPin;
if (
a.nodeElement.getType() == Configuration.nodeType.knot
|| b.nodeElement.getType() == Configuration.nodeType.knot
) {
// A knot can be linked to any pin, it doesn't matter the type or input/output direction
this.link.setMessageCorrect();
this.linkValid = true;
} else if (a.getNodeElement() == b.getNodeElement()) {
this.link.setMessageSameNode();
} else if (a.isOutput() == b.isOutput()) {
this.link.setMessageDirectionsIncompatible();
} else if (a.isOutput() == b.isOutput()) {
this.link.setMessageDirectionsIncompatible();
} else if (this.blueprint.getLinks(a, b).length) {
this.link.setMessageReplaceLink();
this.linkValid = true;
} else {
this.link.setMessageCorrect();
this.linkValid = true;
}
/** @param {MouseEvent} e */
#mouseenterHandler = e => {
if (!this.enteredPin) {
this.linkValid = false;
this.enteredPin = /** @type {PinElement} */(e.target);
const a = this.link.sourcePin ?? this.target; // Remember target might have change
const b = this.enteredPin;
const outputPin = a.isOutput() ? a : b;
if (
a.nodeElement.getType() === Configuration.nodeType.knot
|| b.nodeElement.getType() === Configuration.nodeType.knot
) {
// A knot can be linked to any pin, it doesn't matter the type or input/output direction
this.link.setMessageCorrect();
this.linkValid = true;
} else if (a.getNodeElement() === b.getNodeElement()) {
this.link.setMessageSameNode();
} else if (a.isOutput() === b.isOutput()) {
this.link.setMessageDirectionsIncompatible();
} else if (this.blueprint.getLinks(a, b).length) {
this.link.setMessageReplaceLink();
this.linkValid = true;
} else if (outputPin.entity.getType() === "exec" && outputPin.isLinked) {
this.link.setMessageReplaceOutputLink();
this.linkValid = true;
} else {
this.link.setMessageCorrect();
this.linkValid = true;
}
}
}
#mouseleaveHandler =
/** @param {MouseEvent} e */
e => {
if (this.enteredPin == e.target) {
this.enteredPin = null;
this.linkValid = false;
this.link?.setMessagePlaceNode();
}
/** @param {MouseEvent} e */
#mouseleaveHandler = e => {
if (this.enteredPin == e.target) {
this.enteredPin = null;
this.linkValid = false;
this.link?.setMessagePlaceNode();
}
}
/** @type {LinkElement?} */
link
@@ -6116,15 +6207,15 @@ class MouseCreateLink extends IMouseClickDrag {
const otherPin = this.#knotPin !== this.link.sourcePin ? this.link.sourcePin : this.enteredPin;
// Knot pin direction correction
if (this.#knotPin.isInput() && otherPin.isInput() || this.#knotPin.isOutput() && otherPin.isOutput()) {
const oppositePin = this.#knotPin.isInput()
? /** @type {KnotNodeTemplate} */(this.#knotPin.nodeElement.template).outputPin
: /** @type {KnotNodeTemplate} */(this.#knotPin.nodeElement.template).inputPin;
const oppositePin = /** @type {KnotPinTemplate} */(this.#knotPin.template).getOppositePin();
if (this.#knotPin === this.link.sourcePin) {
this.link.sourcePin = oppositePin;
} else {
this.enteredPin = oppositePin;
}
}
} else if (this.enteredPin.nodeElement.getType() === Configuration.nodeType.knot) {
this.enteredPin = /** @type {KnotPinTemplate} */(this.enteredPin.template).getOppositePin();
}
this.blueprint.addGraphElement(this.link);
this.link.destinationPin = this.enteredPin;
@@ -6324,6 +6415,15 @@ class PinTemplate extends ITemplate {
}
}
/**
* @template T
* @typedef {import("../../element/PinElement").default<T>} PinElement
*/
/**
* @template T
* @extends PinTemplate<PinElement<T>>
*/
class MinimalPinTemplate extends PinTemplate {
render() {
@@ -6443,14 +6543,23 @@ class ISelectableDraggableElement extends IDraggableElement {
}
}
/** @typedef {import("../node/KnotNodeTemplate").default} KnotNodeTemplate */
/**
* @typedef {import("../node/KnotNodeTemplate").default} KnotNodeTemplate
* @typedef {import("../../entity/PinEntity").default} KnotEntity
*/
/** @extends MinimalPinTemplate<KnotEntity> */
class KnotPinTemplate extends MinimalPinTemplate {
render() {
return this.element.isOutput() ? super.render() : y``
}
getOppositePin() {
const nodeTemplate = /** @type {KnotNodeTemplate} */(this.element.nodeElement.template);
return this.element.isOutput() ? nodeTemplate.inputPin : nodeTemplate.outputPin
}
getLinkLocation() {
const rect = (
this.element.isInput()
@@ -6769,11 +6878,6 @@ class NodeElement extends ISelectableDraggableElement {
&& this.leftBoundary() >= commentNode.leftBoundary()
}
cleanup() {
super.cleanup();
this.acknowledgeDelete();
}
getType() {
return this.entity.getType()
}
@@ -6837,13 +6941,9 @@ class NodeElement extends ISelectableDraggableElement {
super.setLocation(x, y, acknowledge);
}
acknowledgeDelete() {
let deleteEvent = new CustomEvent(Configuration.nodeDeleteEventName);
this.dispatchEvent(deleteEvent);
}
acknowledgeReflow() {
this.addNextUpdatedCallbacks(() => this.computeSizes(), true);
this.requestUpdate();
this.updateComplete.then(() => this.computeSizes());
let reflowEvent = new CustomEvent(Configuration.nodeReflowEventName);
this.dispatchEvent(reflowEvent);
}
@@ -7200,10 +7300,10 @@ class Blueprint extends IElement {
* @param {PinElement} sourcePin
* @param {PinElement} destinationPin
*/
getLink(sourcePin, destinationPin, ignoreDirection = false) {
getLink(sourcePin, destinationPin, strictDirection = false) {
return this.links.find(link =>
link.sourcePin == sourcePin && link.destinationPin == destinationPin
|| ignoreDirection && link.sourcePin == destinationPin && link.destinationPin == sourcePin
|| !strictDirection && link.sourcePin == destinationPin && link.destinationPin == sourcePin
)
}
@@ -7217,7 +7317,7 @@ class Blueprint extends IElement {
/** @param {...IElement} graphElements */
addGraphElement(...graphElements) {
for (let element of graphElements) {
for (const element of graphElements) {
element.blueprint = this;
if (element instanceof NodeElement && !this.nodes.includes(element)) {
const nodeName = element.entity.getObjectName();
@@ -7234,9 +7334,23 @@ class Blueprint extends IElement {
homonymNode.rename(Configuration.nodeName(name, this.#nodeNameCounter[name]));
}
this.nodes.push(element);
element.addEventListener(Configuration.removeEventName, () => {
const index = this.nodes.indexOf(element);
const last = this.nodes.pop();
if (this.nodes.length > 0) {
this.nodes[index] = last;
}
});
this.template.nodesContainerElement?.appendChild(element);
} else if (element instanceof LinkElement && !this.links.includes(element)) {
this.links.push(element);
element.addEventListener(Configuration.removeEventName, () => {
const index = this.links.indexOf(element);
const last = this.links.pop();
if (this.nodes.length > 0) {
this.links[index] = last;
}
});
if (this.template.linksContainerElement && !this.template.linksContainerElement.contains(element)) {
this.template.linksContainerElement.appendChild(element);
}
@@ -8371,8 +8485,6 @@ class RotatorPinTemplate extends INumericPinTemplate {
class StringPinTemplate extends IInputPinTemplate {
}
/** @typedef {import("../../entity/LinearColorEntity").default} LinearColorEntity */
/**
* @extends INumericPinTemplate<Vector2DEntity>
*/
@@ -8416,8 +8528,6 @@ class VectorInputPinTemplate extends INumericPinTemplate {
}
}
/** @typedef {import("../../entity/LinearColorEntity").default} LinearColorEntity */
/**
* @extends INumericPinTemplate<VectorEntity>
*/
@@ -8472,7 +8582,6 @@ class VectorPinTemplate extends INumericPinTemplate {
/**
* @typedef {import("../entity/IEntity").AnyValue} AnyValue
* @typedef {import("../entity/PinReferenceEntity").default} PinReferenceEntity
* @typedef {import("./LinkElement").LinkElementConstructor} LinkElementConstructor
* @typedef {import("./NodeElement").default} NodeElement
* @typedef {import("lit").CSSResult} CSSResult
@@ -8602,6 +8711,13 @@ class PinElement extends IElement {
this.nodeElement = this.closest("ueb-node");
}
createPinReference() {
return new PinReferenceEntity({
objectName: this.nodeElement.getNodeName(),
pinGuid: this.getPinId(),
})
}
/** @return {GuidEntity} */
getPinId() {
return this.entity.PinId
@@ -8659,7 +8775,7 @@ class PinElement extends IElement {
if (nodesWhitelist.length && !nodesWhitelist.includes(pin.nodeElement)) {
return false
}
let link = this.blueprint.getLink(this, pin, true);
let link = this.blueprint.getLink(this, pin);
if (!link) {
link = /** @type {LinkElementConstructor} */(ElementFactory.getConstructor("ueb-link"))
.newObject(this, pin);
@@ -8673,6 +8789,14 @@ class PinElement extends IElement {
/** @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();
@@ -8680,10 +8804,21 @@ class PinElement extends IElement {
}
/** @param {PinElement} targetPinElement */
unlinkFrom(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();
}
}
@@ -8692,7 +8827,7 @@ class PinElement extends IElement {
* @param {PinReferenceEntity} newReference
*/
redirectLink(originalPinElement, newReference) {
const index = this.entity.LinkedTo.findIndex(pinReference =>
const index = this.getLinks().findIndex(pinReference =>
pinReference.objectName.toString() == originalPinElement.getNodeElement().getNodeName()
&& pinReference.pinGuid.valueOf() == originalPinElement.entity.PinId.valueOf()
);
@@ -9248,6 +9383,7 @@ function initializeSerializerFactory() {
(array, insideString) =>
`(${array
.map(v =>
// @ts-expect-error
SerializerFactory.getSerializer(Utility.getType(v)).serialize(v, insideString) + ","
)
.join("")
@@ -9281,6 +9417,11 @@ function initializeSerializerFactory() {
new ToStringSerializer(ByteEntity)
);
SerializerFactory.registerSerializer(
EnumEntity,
new ToStringSerializer(EnumEntity)
);
SerializerFactory.registerSerializer(
FunctionReferenceEntity,
new GeneralSerializer(bracketsWrapped, FunctionReferenceEntity)

File diff suppressed because one or more lines are too long

View File

@@ -347,10 +347,10 @@ export default class Blueprint extends IElement {
* @param {PinElement} sourcePin
* @param {PinElement} destinationPin
*/
getLink(sourcePin, destinationPin, ignoreDirection = false) {
getLink(sourcePin, destinationPin, strictDirection = false) {
return this.links.find(link =>
link.sourcePin == sourcePin && link.destinationPin == destinationPin
|| ignoreDirection && link.sourcePin == destinationPin && link.destinationPin == sourcePin
|| !strictDirection && link.sourcePin == destinationPin && link.destinationPin == sourcePin
)
}
@@ -364,8 +364,7 @@ export default class Blueprint extends IElement {
/** @param {...IElement} graphElements */
addGraphElement(...graphElements) {
let nodeElements = []
for (let element of graphElements) {
for (const element of graphElements) {
element.blueprint = this
if (element instanceof NodeElement && !this.nodes.includes(element)) {
const nodeName = element.entity.getObjectName()
@@ -382,10 +381,23 @@ export default class Blueprint extends IElement {
homonymNode.rename(Configuration.nodeName(name, this.#nodeNameCounter[name]))
}
this.nodes.push(element)
nodeElements.push(element)
element.addEventListener(Configuration.removeEventName, () => {
const index = this.nodes.indexOf(element)
const last = this.nodes.pop()
if (this.nodes.length > 0) {
this.nodes[index] = last
}
})
this.template.nodesContainerElement?.appendChild(element)
} else if (element instanceof LinkElement && !this.links.includes(element)) {
this.links.push(element)
element.addEventListener(Configuration.removeEventName, () => {
const index = this.links.indexOf(element)
const last = this.links.pop()
if (this.nodes.length > 0) {
this.links[index] = last
}
})
if (this.template.linksContainerElement && !this.template.linksContainerElement.contains(element)) {
this.template.linksContainerElement.appendChild(element)
}

View File

@@ -18,6 +18,7 @@ export default class Configuration {
"class": css`88, 0, 186`,
"default": css`255, 255, 255`,
"delegate": css`255, 56, 56`,
"enum": css`0, 109, 99`,
"exec": css`240, 240, 240`,
"int": css`31, 224, 172`,
"int64": css`169, 223, 172`,
@@ -76,7 +77,6 @@ export default class Configuration {
static maxZoom = 7
static minZoom = -12
static mouseWheelFactor = 0.2
static nodeDeleteEventName = "ueb-node-delete"
static nodeDragGeneralEventName = "ueb-node-drag-general"
static nodeDragEventName = "ueb-node-drag"
/** @param {NodeElement} node */
@@ -121,8 +121,9 @@ export default class Configuration {
case Configuration.nodeType.makeMap:
case Configuration.nodeType.select:
return pureFunctionColor
case Configuration.nodeType.macro:
case Configuration.nodeType.executionSequence:
case Configuration.nodeType.ifThenElse:
case Configuration.nodeType.macro:
return css`150,150,150`
case Configuration.nodeType.dynamicCast:
return css`46, 104, 106`
@@ -211,6 +212,7 @@ export default class Configuration {
customEvent: "/Script/BlueprintGraph.K2Node_CustomEvent",
doN: "/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:Do N",
dynamicCast: "/Script/BlueprintGraph.K2Node_DynamicCast",
enum: "/Script/CoreUObject.Enum",
event: "/Script/BlueprintGraph.K2Node_Event",
executionSequence: "/Script/BlueprintGraph.K2Node_ExecutionSequence",
forEachElementInEnum: "/Script/BlueprintGraph.K2Node_ForEachElementInEnum",
@@ -242,6 +244,7 @@ export default class Configuration {
?? Configuration.#pinColor[pin.entity.PinType.PinCategory]
?? Configuration.#pinColor["default"]
}
static removeEventName = "ueb-element-delete"
static scale = {
[-12]: 0.133333,
[-11]: 0.166666,

View File

@@ -158,6 +158,10 @@ export default class Utility {
* @param {AnyValue} b
*/
static equals(a, b) {
// Here we cannot check both instanceof IEntity because this would introduce a circular include dependency
if (/** @type {IEntity?} */(a)?.equals && /** @type {IEntity?} */(b)?.equals) {
return /** @type {IEntity} */(a).equals(/** @type {IEntity} */(b))
}
a = Utility.sanitize(a)
b = Utility.sanitize(b)
if (a?.constructor === BigInt && b?.constructor === Number) {
@@ -169,7 +173,15 @@ export default class Utility {
return true
}
if (a instanceof Array && b instanceof Array) {
return a.length == b.length && !a.find((value, i) => !Utility.equals(value, b[i]))
return a.length === b.length && a.every((value, i) => Utility.equals(value, b[i]))
}
if (a instanceof Set && b instanceof Set) {
if (a.size !== b.size) {
return false
}
a = [...a]
b = [...b]
return a.every(first => /** @type {Array} */(b).some(second => Utility.equals(first, second)))
}
return false
}
@@ -183,7 +195,6 @@ export default class Utility {
return null
}
if (value?.constructor === Object && value?.type instanceof Function) {
// @ts-expect-error
return value.type
}
return /** @type {AnyValueConstructor} */(value?.constructor)

View File

@@ -1,4 +1,5 @@
import { LitElement } from "lit"
import Configuration from "../Configuration"
/**
* @typedef {import("../Blueprint").default} Blueprint
@@ -76,6 +77,7 @@ export default class IElement extends LitElement {
if (this.isSetup) {
this.updateComplete.then(() => this.cleanup())
}
this.acknowledgeDelete()
}
createRenderRoot() {
@@ -138,6 +140,11 @@ export default class IElement extends LitElement {
}
}
acknowledgeDelete() {
let deleteEvent = new CustomEvent(Configuration.removeEventName)
this.dispatchEvent(deleteEvent)
}
/** @param {IElement} element */
isSameGraph(element) {
return this.blueprint && this.blueprint == element?.blueprint

View File

@@ -124,7 +124,6 @@ export default class LinkElement extends IFromToPositionedElement {
this.fromY = this.toY
}
}
this.#linkPins()
}
/**
@@ -138,7 +137,7 @@ export default class LinkElement extends IFromToPositionedElement {
}
if (getCurrentPin()) {
const nodeElement = getCurrentPin().getNodeElement()
nodeElement.removeEventListener(Configuration.nodeDeleteEventName, this.#nodeDeleteHandler)
nodeElement.removeEventListener(Configuration.removeEventName, this.#nodeDeleteHandler)
nodeElement.removeEventListener(
Configuration.nodeDragEventName,
isDestinationPin ? this.#nodeDragDestinatonHandler : this.#nodeDragSourceHandler
@@ -154,7 +153,7 @@ export default class LinkElement extends IFromToPositionedElement {
: this.#sourcePin = pin
if (getCurrentPin()) {
const nodeElement = getCurrentPin().getNodeElement()
nodeElement.addEventListener(Configuration.nodeDeleteEventName, this.#nodeDeleteHandler)
nodeElement.addEventListener(Configuration.removeEventName, this.#nodeDeleteHandler)
nodeElement.addEventListener(
Configuration.nodeDragEventName,
isDestinationPin ? this.#nodeDragDestinatonHandler : this.#nodeDragSourceHandler
@@ -179,8 +178,8 @@ export default class LinkElement extends IFromToPositionedElement {
#unlinkPins() {
if (this.sourcePin && this.destinationPin) {
this.sourcePin.unlinkFrom(this.destinationPin)
this.destinationPin.unlinkFrom(this.sourcePin)
this.sourcePin.unlinkFrom(this.destinationPin, false)
this.destinationPin.unlinkFrom(this.sourcePin, false)
}
}
@@ -192,11 +191,12 @@ export default class LinkElement extends IFromToPositionedElement {
}
/** @param {Number[]?} location */
setSourceLocation(location = null) {
setSourceLocation(location = null, canPostpone = true) {
if (location == null) {
const self = this
if (!this.hasUpdated || !this.sourcePin.hasUpdated) {
Promise.all([this.updateComplete, this.sourcePin.updateComplete]).then(() => self.setSourceLocation())
if (canPostpone && (!this.hasUpdated || !this.sourcePin.hasUpdated)) {
Promise.all([this.updateComplete, this.sourcePin.updateComplete])
.then(() => self.setSourceLocation(null, false))
return
}
location = this.sourcePin.template.getLinkLocation()
@@ -207,12 +207,12 @@ export default class LinkElement extends IFromToPositionedElement {
}
/** @param {Number[]?} location */
setDestinationLocation(location = null) {
setDestinationLocation(location = null, canPostpone = true) {
if (location == null) {
const self = this
if (!this.hasUpdated || !this.destinationPin.hasUpdated) {
if (canPostpone && (!this.hasUpdated || !this.destinationPin.hasUpdated)) {
Promise.all([this.updateComplete, this.destinationPin.updateComplete])
.then(() => self.setDestinationLocation())
.then(() => self.setDestinationLocation(null, false))
return
}
location = this.destinationPin.template.getLinkLocation()
@@ -221,6 +221,36 @@ export default class LinkElement extends IFromToPositionedElement {
this.toY = location[1]
}
getInputPin() {
if (this.sourcePin?.isInput()) {
return this.sourcePin
}
return this.destinationPin
}
/** @param {PinElement} pin */
setInputPin(pin) {
if (this.sourcePin?.isInput()) {
this.sourcePin = pin
}
this.destinationPin = pin
}
getOutputPin() {
if (this.destinationPin?.isOutput()) {
return this.destinationPin
}
return this.sourcePin
}
/** @param {PinElement} pin */
setOutputPin(pin) {
if (this.destinationPin?.isOutput()) {
this.destinationPin = pin
}
this.sourcePin = pin
}
startDragging() {
this.dragging = true
}
@@ -264,6 +294,11 @@ export default class LinkElement extends IFromToPositionedElement {
this.linkMessageText = html`Replace existing input connections.`
}
setMessageReplaceOutputLink() {
this.linkMessageIcon = SVGIcon.correct
this.linkMessageText = html`Replace existing output connections.`
}
setMessageSameNode() {
this.linkMessageIcon = SVGIcon.reject
this.linkMessageText = html`Both are on the same node.`

View File

@@ -212,11 +212,6 @@ export default class NodeElement extends ISelectableDraggableElement {
&& this.leftBoundary() >= commentNode.leftBoundary()
}
cleanup() {
super.cleanup()
this.acknowledgeDelete()
}
getType() {
return this.entity.getType()
}
@@ -280,13 +275,9 @@ export default class NodeElement extends ISelectableDraggableElement {
super.setLocation(x, y, acknowledge)
}
acknowledgeDelete() {
let deleteEvent = new CustomEvent(Configuration.nodeDeleteEventName)
this.dispatchEvent(deleteEvent)
}
acknowledgeReflow() {
this.addNextUpdatedCallbacks(() => this.computeSizes(), true)
this.requestUpdate()
this.updateComplete.then(() => this.computeSizes())
let reflowEvent = new CustomEvent(Configuration.nodeReflowEventName)
this.dispatchEvent(reflowEvent)
}

View File

@@ -11,6 +11,7 @@ import LinearColorEntity from "../entity/LinearColorEntity"
import LinearColorPinTemplate from "../template/pin/LinearColorPinTemplate"
import NamePinTemplate from "../template/pin/NamePinTemplate"
import PinEntity from "../entity/PinEntity"
import PinReferenceEntity from "../entity/PinReferenceEntity"
import PinTemplate from "../template/pin/PinTemplate"
import RealPinTemplate from "../template/pin/RealPinTemplate"
import ReferencePinTemplate from "../template/pin/ReferencePinTemplate"
@@ -22,7 +23,6 @@ import VectorPinTemplate from "../template/pin/VectorPinTemplate"
/**
* @typedef {import("../entity/IEntity").AnyValue} AnyValue
* @typedef {import("../entity/PinReferenceEntity").default} PinReferenceEntity
* @typedef {import("./LinkElement").LinkElementConstructor} LinkElementConstructor
* @typedef {import("./NodeElement").default} NodeElement
* @typedef {import("lit").CSSResult} CSSResult
@@ -152,6 +152,13 @@ export default class PinElement extends IElement {
this.nodeElement = this.closest("ueb-node")
}
createPinReference() {
return new PinReferenceEntity({
objectName: this.nodeElement.getNodeName(),
pinGuid: this.getPinId(),
})
}
/** @return {GuidEntity} */
getPinId() {
return this.entity.PinId
@@ -209,7 +216,7 @@ export default class PinElement extends IElement {
if (nodesWhitelist.length && !nodesWhitelist.includes(pin.nodeElement)) {
return false
}
let link = this.blueprint.getLink(this, pin, true)
let link = this.blueprint.getLink(this, pin)
if (!link) {
link = /** @type {LinkElementConstructor} */(ElementFactory.getConstructor("ueb-link"))
.newObject(this, pin)
@@ -223,6 +230,14 @@ export default class PinElement extends IElement {
/** @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()
@@ -230,10 +245,21 @@ export default class PinElement extends IElement {
}
/** @param {PinElement} targetPinElement */
unlinkFrom(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()
}
}
@@ -242,7 +268,7 @@ export default class PinElement extends IElement {
* @param {PinReferenceEntity} newReference
*/
redirectLink(originalPinElement, newReference) {
const index = this.entity.LinkedTo.findIndex(pinReference =>
const index = this.getLinks().findIndex(pinReference =>
pinReference.objectName.toString() == originalPinElement.getNodeElement().getNodeName()
&& pinReference.pinGuid.valueOf() == originalPinElement.entity.PinId.valueOf()
)

View File

@@ -1,5 +1,5 @@
import ByteEntity from "./ByteEntity"
import SymbolEntity from "./SymbolEntity"
export default class EnumEntity extends ByteEntity {
export default class EnumEntity extends SymbolEntity {
}

View File

@@ -52,7 +52,8 @@ export default class IEntity {
const defineAllAttributes = (target, attributes, values = {}, prefix = "") => {
const valuesNames = Object.keys(values)
const attributesNames = Object.keys(attributes)
for (let attributeName of Utility.mergeArrays(attributesNames, valuesNames)) {
const allAttributesNames = Utility.mergeArrays(attributesNames, valuesNames)
for (let attributeName of allAttributesNames) {
let value = Utility.objectGet(values, [attributeName])
/** @type {AttributeInformation} */
let attribute = attributes[attributeName]
@@ -234,4 +235,21 @@ export default class IEntity {
return Object.keys(this).length
- Object.keys(/** @type {typeof IEntity} */(this.constructor).attributes).length
}
/** @param {IEntity} other */
equals(other) {
const thisKeys = Object.keys(this)
const otherKeys = Object.keys(this)
if (thisKeys.length != otherKeys.length) {
return false
}
for (const key of thisKeys) {
if (this[key] instanceof IEntity && !this[key].equals(other[key])) {
return false
} else if (!Utility.equals(this[key], other[key])) {
return false
}
}
return true
}
}

View File

@@ -1,4 +1,6 @@
import ByteEntity from "./ByteEntity"
import Configuration from "../Configuration"
import EnumEntity from "./EnumEntity"
import FunctionReferenceEntity from "./FunctionReferenceEntity"
import GuidEntity from "./GuidEntity"
import IEntity from "./IEntity"
@@ -32,6 +34,7 @@ export default class PinEntity extends IEntity {
"/Script/CoreUObject.Vector2D": Vector2DEntity,
"bool": Boolean,
"byte": ByteEntity,
"enum": EnumEntity,
"exec": String,
"int": IntegerEntity,
"int64": Integer64Entity,
@@ -155,8 +158,18 @@ export default class PinEntity extends IEntity {
}
getType() {
if (this.PinType.PinCategory == "struct" || this.PinType.PinCategory == "object") {
return this.PinType.PinSubCategoryObject.path
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
}
@@ -229,20 +242,18 @@ export default class PinEntity extends IEntity {
* @param {PinEntity} targetPinEntity
*/
linkTo(targetObjectName, targetPinEntity) {
/** @type {PinReferenceEntity[]} */
this.LinkedTo
const linkFound = this.LinkedTo?.find(pinReferenceEntity => {
return pinReferenceEntity.objectName.toString() == targetObjectName
&& pinReferenceEntity.pinGuid.valueOf() == targetPinEntity.PinId.valueOf()
})
const linkFound = this.LinkedTo?.some(pinReferenceEntity =>
pinReferenceEntity.objectName.toString() == targetObjectName
&& pinReferenceEntity.pinGuid.valueOf() == targetPinEntity.PinId.valueOf()
)
if (!linkFound) {
(this.LinkedTo ?? (this.LinkedTo = [])).push(new PinReferenceEntity({
(this.LinkedTo ??= []).push(new PinReferenceEntity({
objectName: targetObjectName,
pinGuid: targetPinEntity.PinId,
}))
return true
}
return false
return false // Already linked
}
/**

View File

@@ -7,6 +7,7 @@ import IMouseClickDrag from "./IMouseClickDrag"
* @typedef {import("../../element/LinkElement").LinkElementConstructor} LinkElementConstructor
* @typedef {import("../../element/PinElement").default} PinElement
* @typedef {import("../../template/node/KnotNodeTemplate").default} KnotNodeTemplate
* @typedef {import("../../template/pin/KnotPinTemplate").default} KnotPinTemplate
*/
/** @extends IMouseClickDrag<PinElement> */
@@ -18,46 +19,46 @@ export default class MouseCreateLink extends IMouseClickDrag {
/** @type {PinElement} */
#knotPin = null
#mouseenterHandler =
/** @param {MouseEvent} e */
e => {
if (!this.enteredPin) {
this.linkValid = false
this.enteredPin = /** @type {PinElement} */(e.target)
const a = this.link.sourcePin ?? this.target // Remember target might have change
const b = this.enteredPin
if (
a.nodeElement.getType() == Configuration.nodeType.knot
|| b.nodeElement.getType() == Configuration.nodeType.knot
) {
// A knot can be linked to any pin, it doesn't matter the type or input/output direction
this.link.setMessageCorrect()
this.linkValid = true
} else if (a.getNodeElement() == b.getNodeElement()) {
this.link.setMessageSameNode()
} else if (a.isOutput() == b.isOutput()) {
this.link.setMessageDirectionsIncompatible()
} else if (a.isOutput() == b.isOutput()) {
this.link.setMessageDirectionsIncompatible()
} else if (this.blueprint.getLinks(a, b).length) {
this.link.setMessageReplaceLink()
this.linkValid = true
} else {
this.link.setMessageCorrect()
this.linkValid = true
}
/** @param {MouseEvent} e */
#mouseenterHandler = e => {
if (!this.enteredPin) {
this.linkValid = false
this.enteredPin = /** @type {PinElement} */(e.target)
const a = this.link.sourcePin ?? this.target // Remember target might have change
const b = this.enteredPin
const outputPin = a.isOutput() ? a : b
if (
a.nodeElement.getType() === Configuration.nodeType.knot
|| b.nodeElement.getType() === Configuration.nodeType.knot
) {
// A knot can be linked to any pin, it doesn't matter the type or input/output direction
this.link.setMessageCorrect()
this.linkValid = true
} else if (a.getNodeElement() === b.getNodeElement()) {
this.link.setMessageSameNode()
} else if (a.isOutput() === b.isOutput()) {
this.link.setMessageDirectionsIncompatible()
} else if (this.blueprint.getLinks(a, b).length) {
this.link.setMessageReplaceLink()
this.linkValid = true
} else if (outputPin.entity.getType() === "exec" && outputPin.isLinked) {
this.link.setMessageReplaceOutputLink()
this.linkValid = true
} else {
this.link.setMessageCorrect()
this.linkValid = true
}
}
}
#mouseleaveHandler =
/** @param {MouseEvent} e */
e => {
if (this.enteredPin == e.target) {
this.enteredPin = null
this.linkValid = false
this.link?.setMessagePlaceNode()
}
/** @param {MouseEvent} e */
#mouseleaveHandler = e => {
if (this.enteredPin == e.target) {
this.enteredPin = null
this.linkValid = false
this.link?.setMessagePlaceNode()
}
}
/** @type {LinkElement?} */
link
@@ -102,15 +103,15 @@ export default class MouseCreateLink extends IMouseClickDrag {
const otherPin = this.#knotPin !== this.link.sourcePin ? this.link.sourcePin : this.enteredPin
// Knot pin direction correction
if (this.#knotPin.isInput() && otherPin.isInput() || this.#knotPin.isOutput() && otherPin.isOutput()) {
const oppositePin = this.#knotPin.isInput()
? /** @type {KnotNodeTemplate} */(this.#knotPin.nodeElement.template).outputPin
: /** @type {KnotNodeTemplate} */(this.#knotPin.nodeElement.template).inputPin
const oppositePin = /** @type {KnotPinTemplate} */(this.#knotPin.template).getOppositePin()
if (this.#knotPin === this.link.sourcePin) {
this.link.sourcePin = oppositePin
} else {
this.enteredPin = oppositePin
}
}
} else if (this.enteredPin.nodeElement.getType() === Configuration.nodeType.knot) {
this.enteredPin = /** @type {KnotPinTemplate} */(this.enteredPin.template).getOppositePin()
}
this.blueprint.addGraphElement(this.link)
this.link.destinationPin = this.enteredPin

View File

@@ -300,7 +300,10 @@ export default class Grammar {
PathSymbolOptSpaces = r => P.regex(/[0-9\w]+(?: [0-9\w]+)+|[0-9\w]+/).map(v => new PathSymbolEntity({ value: v }))
/** @param {Grammar} r */
Symbol = r => P.regex(/\w+/).map(v => new SymbolEntity({ value: v }))
Symbol = r => P.regex(/[a-zA-Z_]\w*/).map(v => new SymbolEntity({ value: v }))
/** @param {Grammar} r */
Enum = r => P.regex(/[a-zA-Z_]\w*/).map(v => new EnumEntity({ value: v }))
/** @param {Grammar} r */
ObjectReference = r => P.alt(

View File

@@ -1,5 +1,6 @@
import ByteEntity from "../entity/ByteEntity"
import CustomSerializer from "./CustomSerializer"
import EnumEntity from "../entity/EnumEntity"
import FunctionReferenceEntity from "../entity/FunctionReferenceEntity"
import GeneralSerializer from "./GeneralSerializer"
import GuidEntity from "../entity/GuidEntity"
@@ -56,6 +57,7 @@ export default function initializeSerializerFactory() {
(array, insideString) =>
`(${array
.map(v =>
// @ts-expect-error
SerializerFactory.getSerializer(Utility.getType(v)).serialize(v, insideString) + ","
)
.join("")
@@ -89,6 +91,11 @@ export default function initializeSerializerFactory() {
new ToStringSerializer(ByteEntity)
)
SerializerFactory.registerSerializer(
EnumEntity,
new ToStringSerializer(EnumEntity)
)
SerializerFactory.registerSerializer(
FunctionReferenceEntity,
new GeneralSerializer(bracketsWrapped, FunctionReferenceEntity)

View File

@@ -69,14 +69,17 @@ export default class LinkTemplate extends IFromToPositionedTemplate {
const knot = /** @type {NodeElementConstructor} */(ElementFactory.getConstructor("ueb-node"))
.newObject(knotEntity)
knot.setLocation(...this.blueprint.snapToGrid(...location))
const knotTemplate = /** @type {KnotNodeTemplate} */(knot.template)
this.blueprint.addGraphElement(knot) // Important: keep it before changing existing links
const inputPin = this.element.getInputPin()
const outputPin = this.element.getOutputPin()
this.element.sourcePin = null
this.element.destinationPin = null
const link = /** @type {LinkElementConstructor} */(ElementFactory.getConstructor("ueb-link"))
.newObject(
/** @type {KnotNodeTemplate} */(knot.template).outputPin,
this.element.destinationPin
)
this.element.destinationPin = /** @type {KnotNodeTemplate} */(knot.template).inputPin
.newObject(outputPin, knotTemplate.inputPin)
this.blueprint.addGraphElement(link)
this.element.sourcePin = knotTemplate.outputPin
this.element.destinationPin = inputPin
}
createInputObjects() {
@@ -98,19 +101,21 @@ export default class LinkTemplate extends IFromToPositionedTemplate {
const sourcePin = this.element.sourcePin
const destinationPin = this.element.destinationPin
if (changedProperties.has("fromX") || changedProperties.has("toX")) {
const from = this.element.fromX
const to = this.element.toX
const isSourceAKnot = sourcePin?.nodeElement.getType() == Configuration.nodeType.knot
const isDestinationAKnot = destinationPin?.nodeElement.getType() == Configuration.nodeType.knot
if (isSourceAKnot && (!destinationPin || isDestinationAKnot)) {
if (sourcePin?.isInput() && this.element.toX > this.element.fromX + Configuration.distanceThreshold) {
if (sourcePin?.isInput() && to > from + Configuration.distanceThreshold) {
this.element.sourcePin = /** @type {KnotNodeTemplate} */(sourcePin.nodeElement.template).outputPin
} else if (sourcePin?.isOutput() && this.element.toX < this.element.fromX - Configuration.distanceThreshold) {
} else if (sourcePin?.isOutput() && to < from - Configuration.distanceThreshold) {
this.element.sourcePin = /** @type {KnotNodeTemplate} */(sourcePin.nodeElement.template).inputPin
}
}
if (isDestinationAKnot && (!sourcePin || isSourceAKnot)) {
if (destinationPin?.isInput() && this.element.toX < this.element.fromX + Configuration.distanceThreshold) {
if (destinationPin?.isInput() && to < from - Configuration.distanceThreshold) {
this.element.destinationPin = /** @type {KnotNodeTemplate} */(destinationPin.nodeElement.template).outputPin
} else if (destinationPin?.isOutput() && this.element.toX > this.element.fromX - Configuration.distanceThreshold) {
} else if (destinationPin?.isOutput() && to > from + Configuration.distanceThreshold) {
this.element.destinationPin = /** @type {KnotNodeTemplate} */(destinationPin.nodeElement.template).inputPin
}
}

View File

@@ -2,14 +2,23 @@ import { html } from "lit"
import MinimalPinTemplate from "./MinimalPinTemplate"
import Utility from "../../Utility"
/** @typedef {import("../node/KnotNodeTemplate").default} KnotNodeTemplate */
/**
* @typedef {import("../node/KnotNodeTemplate").default} KnotNodeTemplate
* @typedef {import("../../entity/PinEntity").default} KnotEntity
*/
/** @extends MinimalPinTemplate<KnotEntity> */
export default class KnotPinTemplate extends MinimalPinTemplate {
render() {
return this.element.isOutput() ? super.render() : html``
}
getOppositePin() {
const nodeTemplate = /** @type {KnotNodeTemplate} */(this.element.nodeElement.template)
return this.element.isOutput() ? nodeTemplate.inputPin : nodeTemplate.outputPin
}
getLinkLocation() {
const rect = (
this.element.isInput()

View File

@@ -1,6 +1,15 @@
import { html } from "lit"
import PinTemplate from "./PinTemplate"
/**
* @template T
* @typedef {import("../../element/PinElement").default<T>} PinElement
*/
/**
* @template T
* @extends PinTemplate<PinElement<T>>
*/
export default class MinimalPinTemplate extends PinTemplate {
render() {

View File

@@ -14,7 +14,6 @@ ueb-link {
* their hover behavior correctly firing.
*/
visibility: hidden;
z-index: 2;
}
ueb-link>svg {

View File

@@ -55,8 +55,8 @@ ueb-blueprint[data-scrolling="false"][data-selecting="false"] .ueb-pin-wrapper:h
.ueb-pin-icon {
color: var(--ueb-pin-color);
width: 13px;
height: 13px;
width: 12px;
height: 12px;
text-align: left;
}
@@ -72,11 +72,10 @@ ueb-blueprint[data-scrolling="false"][data-selecting="false"] .ueb-pin-wrapper:h
vertical-align: top;
}
ueb-pin[data-type="exec"] .ueb-pin-icon>svg {
--ueb-pin-color: white;
ueb-pin[data-type="exec"] .ueb-pin-icon {
width: 15px;
height: 15px;
vertical-align: middle;
--ueb-pin-color: white;
}
ueb-pin[data-linked="true"] .ueb-pin-tofill {