mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-02-03 23:55:04 +08:00
Various fixes, tests and refactoring
This commit is contained in:
@@ -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", () => {
|
||||
|
||||
@@ -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
|
||||
|
||||
10
dist/css/ueb-style.css
vendored
10
dist/css/ueb-style.css
vendored
@@ -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 {
|
||||
|
||||
2
dist/css/ueb-style.css.map
vendored
2
dist/css/ueb-style.css.map
vendored
@@ -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"}
|
||||
2
dist/css/ueb-style.min.css
vendored
2
dist/css/ueb-style.min.css
vendored
File diff suppressed because one or more lines are too long
2
dist/css/ueb-style.min.css.map
vendored
2
dist/css/ueb-style.min.css.map
vendored
@@ -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
377
dist/ueblueprint.js
vendored
@@ -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)
|
||||
|
||||
6
dist/ueblueprint.min.js
vendored
6
dist/ueblueprint.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.`
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ByteEntity from "./ByteEntity"
|
||||
import SymbolEntity from "./SymbolEntity"
|
||||
|
||||
export default class EnumEntity extends ByteEntity {
|
||||
export default class EnumEntity extends SymbolEntity {
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -14,7 +14,6 @@ ueb-link {
|
||||
* their hover behavior correctly firing.
|
||||
*/
|
||||
visibility: hidden;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
ueb-link>svg {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user