Files
ueblueprint/js/input/mouse/MouseCreateLink.js
BarsDev 6ba2705386 Large refactoring and new nodes
* Fix node reference when changing elements

* Fix ScriptVariables parsing

* Fix invariant text and niagara types

* Niagara convert nodes

* Move node tests to own files

* More Niagara tests

* Niagara float and smaller fixes

* More Decoding

* More decoding

* WIP

* Float is real

* WIP

* More types and colors

* Test case and small polish

* WIP

* WIP

* Fix niagara script variables merging

* Fix Niagara variables

* Fixing mirrored ExportPath

* Fix Export paths name adjustments

* Simplify arc calculation

* Simplify a bit arc calculation

* source / destionation => origin / target

* Minor refactoring

* Fix switched link position

* Rename some properties for uniformity

* Fix input escape

* Simplify test

* About window

* Dialog backdrop style

* About dialog touches

* Remove dependency and minot improvement

* Light mode

* Fix link location and css small improvement

* Link direction and minor fixes

* Some minor fixes and refactoring

* Refactoring WIP

* Shorting repetitive bits

* More tests

* Simplify linking tests
2025-02-07 00:36:03 +02:00

143 lines
5.5 KiB
JavaScript
Executable File

import Configuration from "../../Configuration.js"
import ElementFactory from "../../element/ElementFactory.js"
import IMouseClickDrag from "./IMouseClickDrag.js"
/**
* @typedef {import("./IMouseClickDrag.js").Options & {
* scrollGraphEdge?: Boolean,
* }} Options
*/
/** @extends IMouseClickDrag<PinElement> */
export default class MouseCreateLink extends IMouseClickDrag {
/** @type {NodeListOf<PinElement>} */
#listenedPins
/** @param {MouseEvent} e */
#mouseenterHandler = e => {
if (!this.enteredPin) {
this.linkValid = false
this.enteredPin = /** @type {PinElement} */(e.target)
const a = this.link.origin ?? this.target // Remember target might have change
const b = this.enteredPin
const outputPin = a.isOutput() ? a : b
if (a.isKnot() || b.isKnot()) {
// 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 if (
(a.entity.PinType.PinCategory.valueOf() != "object" || b.entity.PinType.PinCategory.valueOf() != "object")
&& a.pinType != b.pinType
) {
this.link.setMessageTypesIncompatible(a, b)
this.linkValid = false
} else {
this.link.setMessageCorrect()
this.linkValid = true
}
}
}
/** @param {MouseEvent} e */
#mouseleaveHandler = e => {
if (this.enteredPin == e.target) {
this.enteredPin = null
this.linkValid = false
this.link?.setMessagePlaceNode()
}
}
/** @type {LinkElement?} */
link
/** @type {PinElement?} */
enteredPin
linkValid = false
/**
* @param {PinElement} target
* @param {Blueprint} blueprint
* @param {Options} options
*/
constructor(target, blueprint, options = {}) {
options.scrollGraphEdge ??= true
super(target, blueprint, options)
}
startDrag(location) {
/** @type {LinkElement} */
this.link = /** @type {LinkElementConstructor} */(ElementFactory.getConstructor("ueb-link"))
.newObject(this.target, null)
this.blueprint.template.linksContainerElement.prepend(this.link)
this.link.setMessagePlaceNode()
this.#listenedPins = this.blueprint.querySelectorAll("ueb-pin")
this.#listenedPins.forEach(pin => {
if (pin != this.target) {
pin.addEventListener("mouseenter", this.#mouseenterHandler)
pin.addEventListener("mouseleave", this.#mouseleaveHandler)
}
})
this.link.startDragging()
this.link.setTargetLocation(location)
}
dragTo(location, movement) {
this.link.setTargetLocation(location)
}
endDrag() {
this.#listenedPins.forEach(pin => {
pin.removeEventListener("mouseenter", this.#mouseenterHandler)
pin.removeEventListener("mouseleave", this.#mouseleaveHandler)
})
this.#listenedPins = null
if (this.enteredPin && this.linkValid) {
const knot = this.enteredPin.isKnot()
? this.enteredPin
: this.link.origin.isKnot() ? this.link.origin : null
// Knot can use wither the input or output (by default) part indifferently, check if a switch is needed
if (knot) {
const otherPin = knot !== this.link.origin ? this.link.origin : this.enteredPin
// Knot pin direction correction
if (knot.isInput() && otherPin.isInput() || knot.isOutput() && otherPin.isOutput()) {
const oppositePin = /** @type {KnotPinTemplate} */(knot.template).getoppositePin()
if (knot === this.link.origin) {
this.link.origin = oppositePin
} else {
this.enteredPin = oppositePin
}
}
} else if (this.enteredPin.isKnot()) {
if (this.link.origin.isOutput()) {
// Knot uses by default the output pin, let's switch to keep it coherent with the origin node we have
this.enteredPin = /** @type {KnotPinTemplate} */(this.enteredPin.template).getoppositePin()
}
}
if (!this.link.origin.getLinks().find(ref => ref.equals(this.enteredPin.createPinReference()))) {
this.blueprint.addGraphElement(this.link)
this.link.target = this.enteredPin
} else {
this.link.remove()
}
} else {
this.link.remove()
}
this.enteredPin = null
this.link.removeMessage()
this.link.finishDragging()
this.link = null
}
}