mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-02-04 08:50:33 +08:00
* 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
143 lines
5.5 KiB
JavaScript
Executable File
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
|
|
}
|
|
}
|