mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-05-23 22:57:29 +08:00
Avoid using arrays when unnecessary
This commit is contained in:
@@ -117,30 +117,32 @@ export default class Blueprint extends IElement {
|
||||
return [this.scrollX, this.scrollY]
|
||||
}
|
||||
|
||||
/** @param {Number[]} param0 */
|
||||
setScroll([x, y]) {
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
*/
|
||||
setScroll(x, y) {
|
||||
this.scrollX = x
|
||||
this.scrollY = y
|
||||
}
|
||||
|
||||
/** @param {Number[]} delta */
|
||||
scrollDelta(delta, smooth = false) {
|
||||
scrollDelta(x = 0, y = 0, smooth = false) {
|
||||
if (smooth) {
|
||||
let previousScrollDelta = [0, 0]
|
||||
Utility.animate(0, delta[0], Configuration.smoothScrollTime, x => {
|
||||
this.scrollDelta([x - previousScrollDelta[0], 0], false)
|
||||
Utility.animate(0, x, Configuration.smoothScrollTime, x => {
|
||||
this.scrollDelta(x - previousScrollDelta[0], 0, false)
|
||||
previousScrollDelta[0] = x
|
||||
})
|
||||
Utility.animate(0, delta[1], Configuration.smoothScrollTime, y => {
|
||||
this.scrollDelta([0, y - previousScrollDelta[1]], false)
|
||||
Utility.animate(0, y, Configuration.smoothScrollTime, y => {
|
||||
this.scrollDelta(0, y - previousScrollDelta[1], false)
|
||||
previousScrollDelta[1] = y
|
||||
})
|
||||
} else {
|
||||
const maxScroll = [2 * Configuration.expandGridSize, 2 * Configuration.expandGridSize]
|
||||
let currentScroll = this.getScroll()
|
||||
let finalScroll = [
|
||||
currentScroll[0] + delta[0],
|
||||
currentScroll[1] + delta[1]
|
||||
currentScroll[0] + x,
|
||||
currentScroll[1] + y
|
||||
]
|
||||
let expand = [0, 0]
|
||||
for (let i = 0; i < 2; ++i) {
|
||||
@@ -156,14 +158,14 @@ export default class Blueprint extends IElement {
|
||||
}
|
||||
}
|
||||
if (expand[0] != 0 || expand[1] != 0) {
|
||||
this.seamlessExpand(expand)
|
||||
this.seamlessExpand(expand[0], expand[1])
|
||||
}
|
||||
currentScroll = this.getScroll()
|
||||
finalScroll = [
|
||||
currentScroll[0] + delta[0],
|
||||
currentScroll[1] + delta[1]
|
||||
currentScroll[0] + x,
|
||||
currentScroll[1] + y
|
||||
]
|
||||
this.setScroll(finalScroll)
|
||||
this.setScroll(finalScroll[0], finalScroll[1])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +180,7 @@ export default class Blueprint extends IElement {
|
||||
offset[0] - targetOffset[0],
|
||||
offset[1] - targetOffset[1]
|
||||
]
|
||||
this.scrollDelta(deltaOffset, true)
|
||||
this.scrollDelta(deltaOffset[0], deltaOffset[1], true)
|
||||
}
|
||||
|
||||
getViewportSize() {
|
||||
@@ -195,12 +197,19 @@ export default class Blueprint extends IElement {
|
||||
]
|
||||
}
|
||||
|
||||
snapToGrid(location) {
|
||||
return Utility.snapToGrid(location, Configuration.gridSize)
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
*/
|
||||
snapToGrid(x, y) {
|
||||
return Utility.snapToGrid(x, y, Configuration.gridSize)
|
||||
}
|
||||
|
||||
/** @param {Number[]} param0 */
|
||||
seamlessExpand([x, y]) {
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
*/
|
||||
seamlessExpand(x, y) {
|
||||
x = Math.round(x)
|
||||
y = Math.round(y)
|
||||
let scale = this.getScale()
|
||||
@@ -237,19 +246,17 @@ export default class Blueprint extends IElement {
|
||||
this.zoom = zoom
|
||||
|
||||
if (center) {
|
||||
//requestAnimationFrame(_ => {
|
||||
center[0] += this.translateX
|
||||
center[1] += this.translateY
|
||||
let relativeScale = this.getScale() / initialScale
|
||||
let newCenter = [
|
||||
relativeScale * center[0],
|
||||
relativeScale * center[1],
|
||||
]
|
||||
this.scrollDelta([
|
||||
(newCenter[0] - center[0]) * initialScale,
|
||||
(newCenter[1] - center[1]) * initialScale,
|
||||
])
|
||||
//})
|
||||
center[0] += this.translateX
|
||||
center[1] += this.translateY
|
||||
let relativeScale = this.getScale() / initialScale
|
||||
let newCenter = [
|
||||
relativeScale * center[0],
|
||||
relativeScale * center[1],
|
||||
]
|
||||
this.scrollDelta(
|
||||
(newCenter[0] - center[0]) * initialScale,
|
||||
(newCenter[1] - center[1]) * initialScale,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,8 +264,12 @@ export default class Blueprint extends IElement {
|
||||
return Configuration.scale[this.getZoom()]
|
||||
}
|
||||
|
||||
/** @param {Number[]} param0 */
|
||||
compensateTranslation([x, y]) {
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
* @returns {[Number, Number]}
|
||||
*/
|
||||
compensateTranslation(x, y) {
|
||||
x -= this.translateX
|
||||
y -= this.translateY
|
||||
return [x, y]
|
||||
@@ -315,11 +326,11 @@ export default class Blueprint extends IElement {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of links in this blueprint.
|
||||
* @returns {LinkElement[]} Nodes
|
||||
* @param {PinElement?} a
|
||||
* @param {PinElement?} b
|
||||
*/
|
||||
getLinks([a, b] = []) {
|
||||
if (a == null != b == null) {
|
||||
getLinks(a = null, b = null) {
|
||||
if ((a == null) != (b == null)) {
|
||||
const pin = a ?? b
|
||||
return this.links.filter(link => link.sourcePin == pin || link.destinationPin == pin)
|
||||
}
|
||||
|
||||
@@ -31,12 +31,14 @@ export default class Utility {
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {Number} x */
|
||||
static sigmoid(x, curvature = 1.7) {
|
||||
return 1 / (1 + (x / (1 - x) ** -curvature))
|
||||
}
|
||||
|
||||
static clamp(val, min = -Infinity, max = Infinity) {
|
||||
return Math.min(Math.max(val, min), max)
|
||||
/** @param {Number} value */
|
||||
static clamp(value, min = -Infinity, max = Infinity) {
|
||||
return Math.min(Math.max(value, min), max)
|
||||
}
|
||||
|
||||
/** @param {HTMLElement} element */
|
||||
@@ -217,16 +219,18 @@ export default class Utility {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number[]} location
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
* @param {Number} gridSize
|
||||
* @returns {[Number, Number]}
|
||||
*/
|
||||
static snapToGrid(location, gridSize) {
|
||||
static snapToGrid(x, y, gridSize) {
|
||||
if (gridSize === 1) {
|
||||
return location
|
||||
return [x, y]
|
||||
}
|
||||
return [
|
||||
gridSize * Math.round(location[0] / gridSize),
|
||||
gridSize * Math.round(location[1] / gridSize)
|
||||
gridSize * Math.round(x / gridSize),
|
||||
gridSize * Math.round(y / gridSize)
|
||||
]
|
||||
}
|
||||
|
||||
@@ -318,8 +322,12 @@ export default class Utility {
|
||||
return `${Math.round(value.R.valueOf() * 255)}, ${Math.round(value.G.valueOf() * 255)}, ${Math.round(value.B.valueOf() * 255)}`
|
||||
}
|
||||
|
||||
/** @param {[Number, Number]} param0 */
|
||||
static getPolarCoordinates([x, y], positiveTheta = false) {
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
* @returns {[Number, Number]}
|
||||
*/
|
||||
static getPolarCoordinates(x, y, positiveTheta = false) {
|
||||
let theta = Math.atan2(y, x)
|
||||
if (positiveTheta && theta < 0) {
|
||||
theta = 2 * Math.PI + theta
|
||||
@@ -330,8 +338,12 @@ export default class Utility {
|
||||
]
|
||||
}
|
||||
|
||||
/** @param {[Number, Number]} param0 */
|
||||
static getCartesianCoordinates([r, theta]) {
|
||||
/**
|
||||
* @param {Number} r
|
||||
* @param {Number} theta
|
||||
* @returns {[Number, Number]}
|
||||
*/
|
||||
static getCartesianCoordinates(r, theta) {
|
||||
return [
|
||||
r * Math.cos(theta),
|
||||
r * Math.sin(theta)
|
||||
|
||||
@@ -21,8 +21,11 @@ export default class IDraggableControlElement extends IDraggableElement {
|
||||
this.windowElement = this.closest("ueb-window")
|
||||
}
|
||||
|
||||
/** @param {Number[]} param0 */
|
||||
setLocation([x, y]) {
|
||||
super.setLocation(this.template.adjustLocation([x, y]))
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
*/
|
||||
setLocation(x, y) {
|
||||
super.setLocation(...this.template.adjustLocation(x, y))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ import Utility from "../Utility"
|
||||
/**
|
||||
* @typedef {import("../entity/IEntity").default} IEntity
|
||||
* @typedef {import("../template/IDraggableTemplate").default} IDraggableTemplate
|
||||
* @typedef {CustomEvent<{
|
||||
* value: [Number, Number]
|
||||
* }>} DragEvent
|
||||
* @typedef {import("lit").PropertyValues} PropertyValues
|
||||
*/
|
||||
|
||||
@@ -58,9 +61,13 @@ export default class IDraggableElement extends IElement {
|
||||
this.computeSizes()
|
||||
}
|
||||
|
||||
/** @param {Number[]} param0 */
|
||||
setLocation([x, y], acknowledge = true) {
|
||||
const d = [x - this.locationX, y - this.locationY]
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
*/
|
||||
setLocation(x, y, acknowledge = true) {
|
||||
const dx = x - this.locationX
|
||||
const dy = y - this.locationY
|
||||
this.locationX = x
|
||||
this.locationY = y
|
||||
if (this.blueprint && acknowledge) {
|
||||
@@ -68,7 +75,7 @@ export default class IDraggableElement extends IElement {
|
||||
/** @type {typeof IDraggableElement} */(this.constructor).dragEventName,
|
||||
{
|
||||
detail: {
|
||||
value: d,
|
||||
value: [dx, dy],
|
||||
},
|
||||
bubbles: false,
|
||||
cancelable: true,
|
||||
@@ -78,9 +85,12 @@ export default class IDraggableElement extends IElement {
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {Number[]} param0 */
|
||||
addLocation([x, y], acknowledge = true) {
|
||||
this.setLocation([this.locationX + x, this.locationY + y], acknowledge)
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
*/
|
||||
addLocation(x, y, acknowledge = true) {
|
||||
this.setLocation(this.locationX + x, this.locationY + y, acknowledge)
|
||||
}
|
||||
|
||||
/** @param {Number[]} value */
|
||||
@@ -99,9 +109,9 @@ export default class IDraggableElement extends IElement {
|
||||
}
|
||||
|
||||
snapToGrid() {
|
||||
const snappedLocation = Utility.snapToGrid([this.locationX, this.locationY], Configuration.gridSize)
|
||||
const snappedLocation = Utility.snapToGrid(this.locationX, this.locationY, Configuration.gridSize)
|
||||
if (this.locationX != snappedLocation[0] || this.locationY != snappedLocation[1]) {
|
||||
this.setLocation(snappedLocation)
|
||||
this.setLocation(snappedLocation[0], snappedLocation[1])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,15 +48,21 @@ export default class IFromToPositionedElement extends IElement {
|
||||
this.toY = y
|
||||
}
|
||||
|
||||
/** @param {Number[]} offset */
|
||||
addSourceLocation([offsetX, offsetY]) {
|
||||
this.fromX += offsetX
|
||||
this.fromY += offsetY
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
*/
|
||||
addSourceLocation(x, y) {
|
||||
this.fromX += x
|
||||
this.fromY += y
|
||||
}
|
||||
|
||||
/** @param {Number[]} offset */
|
||||
addDestinationLocation([offsetX, offsetY]) {
|
||||
this.toX += offsetX
|
||||
this.toY += offsetY
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
*/
|
||||
addDestinationLocation(x, y) {
|
||||
this.toX += x
|
||||
this.toY += y
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,9 @@ import Utility from "../Utility"
|
||||
import IDraggableElement from "./IDraggableElement"
|
||||
|
||||
/**
|
||||
* @typedef {import("../template/ISelectableDraggableTemplate").default} ISelectableDraggableTemplate
|
||||
* @typedef {import("../element/IDraggableElement").DragEvent} DragEvent
|
||||
* @typedef {import("../entity/IEntity").default} IEntity
|
||||
* @typedef {import("../template/ISelectableDraggableTemplate").default} ISelectableDraggableTemplate
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -24,7 +25,8 @@ export default class ISelectableDraggableElement extends IDraggableElement {
|
||||
},
|
||||
}
|
||||
|
||||
dragHandler = e => this.addLocation(e.detail.value)
|
||||
/** @param {DragEvent} e */
|
||||
dragHandler = e => this.addLocation(...e.detail.value)
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
@@ -6,6 +6,7 @@ import SVGIcon from "../SVGIcon"
|
||||
import Utility from "../Utility"
|
||||
|
||||
/**
|
||||
* @typedef {import("../element/IDraggableElement").DragEvent} DragEvent
|
||||
* @typedef {import("./PinElement").default} PinElement
|
||||
* @typedef {import("lit").TemplateResult<1>} TemplateResult
|
||||
* @typedef {typeof LinkElement} LinkElementConstructor
|
||||
@@ -67,8 +68,10 @@ export default class LinkElement extends IFromToPositionedElement {
|
||||
}
|
||||
|
||||
#nodeDeleteHandler = () => this.remove()
|
||||
#nodeDragSourceHandler = e => this.addSourceLocation(e.detail.value)
|
||||
#nodeDragDestinatonHandler = e => this.addDestinationLocation(e.detail.value)
|
||||
/** @param {DragEvent} e */
|
||||
#nodeDragSourceHandler = e => this.addSourceLocation(...e.detail.value)
|
||||
/** @param {DragEvent} e */
|
||||
#nodeDragDestinatonHandler = e => this.addDestinationLocation(...e.detail.value)
|
||||
#nodeReflowSourceHandler = e => this.setSourceLocation()
|
||||
#nodeReflowDestinatonHandler = e => this.setDestinationLocation()
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import VariableConversionNodeTemplate from "../template/node/VariableConversionN
|
||||
import VariableOperationNodeTemplate from "../template/node/VariableOperationNodeTemplate"
|
||||
|
||||
/**
|
||||
* @typedef {import("./IDraggableElement").DragEvent} DragEvent
|
||||
* @typedef {import("./IElement").default} IElement
|
||||
* @typedef {import("./PinElement").default} PinElement
|
||||
* @typedef {typeof NodeElement} NodeElementConstructor
|
||||
@@ -22,9 +23,6 @@ import VariableOperationNodeTemplate from "../template/node/VariableOperationNod
|
||||
/** @extends {ISelectableDraggableElement<ObjectEntity, NodeTemplate>} */
|
||||
export default class NodeElement extends ISelectableDraggableElement {
|
||||
|
||||
static #typeTemplateMap = {
|
||||
}
|
||||
|
||||
static properties = {
|
||||
...ISelectableDraggableElement.properties,
|
||||
typePath: {
|
||||
@@ -84,12 +82,13 @@ export default class NodeElement extends ISelectableDraggableElement {
|
||||
/** @type {NodeElement[]} */
|
||||
boundComments = []
|
||||
#commentDragged = false
|
||||
/** @param {DragEvent} e */
|
||||
#commentDragHandler = e => {
|
||||
// If selected, it will already drag, also must check if under nested comments, it must drag just once
|
||||
if (!this.selected && !this.#commentDragged) {
|
||||
this.#commentDragged = true
|
||||
this.addNextUpdatedCallbacks(() => this.#commentDragged = false)
|
||||
this.addLocation(e.detail.value)
|
||||
this.addLocation(...e.detail.value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +159,7 @@ export default class NodeElement extends ISelectableDraggableElement {
|
||||
this.nodeDisplayName = this.getNodeDisplayName()
|
||||
this.pureFunction = this.entity.bIsPureFunc
|
||||
this.dragLinkObjects = []
|
||||
super.setLocation([this.entity.NodePosX.value, this.entity.NodePosY.value])
|
||||
super.setLocation(this.entity.NodePosX.value, this.entity.NodePosY.value)
|
||||
if (this.entity.NodeWidth && this.entity.NodeHeight) {
|
||||
this.sizeX = this.entity.NodeWidth.value
|
||||
this.sizeY = this.entity.NodeHeight.value
|
||||
@@ -318,10 +317,10 @@ export default class NodeElement extends ISelectableDraggableElement {
|
||||
return this.entity.CustomProperties.filter(v => v instanceof PinEntity)
|
||||
}
|
||||
|
||||
setLocation(value = [0, 0], acknowledge = true) {
|
||||
this.entity.NodePosX.value = value[0]
|
||||
this.entity.NodePosY.value = value[1]
|
||||
super.setLocation(value, acknowledge)
|
||||
setLocation(x = 0, y = 0, acknowledge = true) {
|
||||
this.entity.NodePosX.value = x
|
||||
this.entity.NodePosY.value = y
|
||||
super.setLocation(x, y, acknowledge)
|
||||
}
|
||||
|
||||
acknowledgeDelete() {
|
||||
|
||||
@@ -164,8 +164,14 @@ export default class LinearColorEntity extends IEntity {
|
||||
this.V.value = v
|
||||
}
|
||||
|
||||
setFromWheelLocation([x, y], v, a) {
|
||||
const [r, theta] = Utility.getPolarCoordinates([x, y], true)
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
* @param {Number} v
|
||||
* @param {Number} a
|
||||
*/
|
||||
setFromWheelLocation(x, y, v, a) {
|
||||
const [r, theta] = Utility.getPolarCoordinates(x, y, true)
|
||||
this.setFromHSVA(1 - theta / (2 * Math.PI), r, v, a)
|
||||
}
|
||||
|
||||
@@ -215,19 +221,19 @@ export default class LinearColorEntity extends IEntity {
|
||||
|
||||
/** @param {Number} number */
|
||||
setFromRGBANumber(number) {
|
||||
this.A.value = (number & 0xFF) / 0xff
|
||||
this.B.value = ((number >> 8) & 0xFF) / 0xff
|
||||
this.G.value = ((number >> 16) & 0xFF) / 0xff
|
||||
this.R.value = ((number >> 24) & 0xFF) / 0xff
|
||||
this.A.value = (number & 0xff) / 0xff
|
||||
this.B.value = ((number >> 8) & 0xff) / 0xff
|
||||
this.G.value = ((number >> 16) & 0xff) / 0xff
|
||||
this.R.value = ((number >> 24) & 0xff) / 0xff
|
||||
this.#updateHSV()
|
||||
}
|
||||
|
||||
/** @param {Number} number */
|
||||
setFromSRGBANumber(number) {
|
||||
this.A.value = (number & 0xFF) / 0xff
|
||||
this.B.value = LinearColorEntity.sRGBtoLinear(((number >> 8) & 0xFF) / 0xff)
|
||||
this.G.value = LinearColorEntity.sRGBtoLinear(((number >> 16) & 0xFF) / 0xff)
|
||||
this.R.value = LinearColorEntity.sRGBtoLinear(((number >> 24) & 0xFF) / 0xff)
|
||||
this.A.value = (number & 0xff) / 0xff
|
||||
this.B.value = LinearColorEntity.sRGBtoLinear(((number >> 8) & 0xff) / 0xff)
|
||||
this.G.value = LinearColorEntity.sRGBtoLinear(((number >> 16) & 0xff) / 0xff)
|
||||
this.R.value = LinearColorEntity.sRGBtoLinear(((number >> 24) & 0xff) / 0xff)
|
||||
this.#updateHSV()
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ export default class Paste extends IInput {
|
||||
window.removeEventListener("paste", this.#pasteHandle)
|
||||
}
|
||||
|
||||
/** @param {String} value */
|
||||
pasted(value) {
|
||||
let top = 0
|
||||
let left = 0
|
||||
@@ -50,11 +51,7 @@ export default class Paste extends IInput {
|
||||
}
|
||||
let mousePosition = this.blueprint.mousePosition
|
||||
nodes.forEach(node => {
|
||||
const locationOffset = [
|
||||
mousePosition[0] - left,
|
||||
mousePosition[1] - top,
|
||||
]
|
||||
node.addLocation(locationOffset)
|
||||
node.addLocation(mousePosition[0] - left, mousePosition[1] - top)
|
||||
node.snapToGrid()
|
||||
node.setSelected(true)
|
||||
})
|
||||
|
||||
@@ -14,96 +14,92 @@ import Utility from "../../Utility"
|
||||
*/
|
||||
export default class IMouseClickDrag extends IPointing {
|
||||
|
||||
#mouseDownHandler =
|
||||
/** @param {MouseEvent} e */
|
||||
e => {
|
||||
this.blueprint.setFocused(true)
|
||||
switch (e.button) {
|
||||
case this.options.clickButton:
|
||||
// Either doesn't matter or consider the click only when clicking on the parent, not descandants
|
||||
if (!this.options.strictTarget || e.target == e.currentTarget) {
|
||||
if (this.options.consumeEvent) {
|
||||
e.stopImmediatePropagation() // Captured, don't call anyone else
|
||||
}
|
||||
// Attach the listeners
|
||||
this.#movementListenedElement.addEventListener("mousemove", this.#mouseStartedMovingHandler)
|
||||
document.addEventListener("mouseup", this.#mouseUpHandler)
|
||||
this.clickedPosition = this.locationFromEvent(e)
|
||||
this.blueprint.mousePosition[0] = this.clickedPosition[0]
|
||||
this.blueprint.mousePosition[1] = this.clickedPosition[1]
|
||||
if (this.target instanceof IDraggableElement) {
|
||||
this.clickedOffset = [
|
||||
this.clickedPosition[0] - this.target.locationX,
|
||||
this.clickedPosition[1] - this.target.locationY,
|
||||
]
|
||||
}
|
||||
this.clicked(this.clickedPosition)
|
||||
/** @param {MouseEvent} e */
|
||||
#mouseDownHandler = e => {
|
||||
this.blueprint.setFocused(true)
|
||||
switch (e.button) {
|
||||
case this.options.clickButton:
|
||||
// Either doesn't matter or consider the click only when clicking on the parent, not descandants
|
||||
if (!this.options.strictTarget || e.target == e.currentTarget) {
|
||||
if (this.options.consumeEvent) {
|
||||
e.stopImmediatePropagation() // Captured, don't call anyone else
|
||||
}
|
||||
break
|
||||
default:
|
||||
if (!this.options.exitAnyButton) {
|
||||
this.#mouseUpHandler(e)
|
||||
// Attach the listeners
|
||||
this.#movementListenedElement.addEventListener("mousemove", this.#mouseStartedMovingHandler)
|
||||
document.addEventListener("mouseup", this.#mouseUpHandler)
|
||||
this.clickedPosition = this.locationFromEvent(e)
|
||||
this.blueprint.mousePosition[0] = this.clickedPosition[0]
|
||||
this.blueprint.mousePosition[1] = this.clickedPosition[1]
|
||||
if (this.target instanceof IDraggableElement) {
|
||||
this.clickedOffset = [
|
||||
this.clickedPosition[0] - this.target.locationX,
|
||||
this.clickedPosition[1] - this.target.locationY,
|
||||
]
|
||||
}
|
||||
break
|
||||
}
|
||||
this.clicked(this.clickedPosition)
|
||||
}
|
||||
break
|
||||
default:
|
||||
if (!this.options.exitAnyButton) {
|
||||
this.#mouseUpHandler(e)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
#mouseStartedMovingHandler =
|
||||
/** @param {MouseEvent} e */
|
||||
e => {
|
||||
/** @param {MouseEvent} e */
|
||||
#mouseStartedMovingHandler = e => {
|
||||
if (this.options.consumeEvent) {
|
||||
e.stopImmediatePropagation() // Captured, don't call anyone else
|
||||
}
|
||||
// Delegate from now on to this.#mouseMoveHandler
|
||||
this.#movementListenedElement.removeEventListener("mousemove", this.#mouseStartedMovingHandler)
|
||||
this.#movementListenedElement.addEventListener("mousemove", this.#mouseMoveHandler)
|
||||
// Handler calls e.preventDefault() when it receives the event, this means dispatchEvent returns false
|
||||
const dragEvent = this.getEvent(Configuration.trackingMouseEventName.begin)
|
||||
this.#trackingMouse = this.target.dispatchEvent(dragEvent) == false
|
||||
const location = this.locationFromEvent(e)
|
||||
// Do actual actions
|
||||
this.lastLocation = Utility.snapToGrid(this.clickedPosition[0], this.clickedPosition[1], this.stepSize)
|
||||
this.startDrag(location)
|
||||
this.started = true
|
||||
}
|
||||
|
||||
/** @param {MouseEvent} e */
|
||||
#mouseMoveHandler = e => {
|
||||
if (this.options.consumeEvent) {
|
||||
e.stopImmediatePropagation() // Captured, don't call anyone else
|
||||
}
|
||||
const location = this.locationFromEvent(e)
|
||||
const movement = [e.movementX, e.movementY]
|
||||
this.dragTo(location, movement)
|
||||
if (this.#trackingMouse) {
|
||||
this.blueprint.mousePosition = this.locationFromEvent(e)
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {MouseEvent} e */
|
||||
#mouseUpHandler = e => {
|
||||
if (!this.options.exitAnyButton || e.button == this.options.clickButton) {
|
||||
if (this.options.consumeEvent) {
|
||||
e.stopImmediatePropagation() // Captured, don't call anyone else
|
||||
}
|
||||
// Delegate from now on to this.#mouseMoveHandler
|
||||
// Remove the handlers of "mousemove" and "mouseup"
|
||||
this.#movementListenedElement.removeEventListener("mousemove", this.#mouseStartedMovingHandler)
|
||||
this.#movementListenedElement.addEventListener("mousemove", this.#mouseMoveHandler)
|
||||
// Handler calls e.preventDefault() when it receives the event, this means dispatchEvent returns false
|
||||
const dragEvent = this.getEvent(Configuration.trackingMouseEventName.begin)
|
||||
this.#trackingMouse = this.target.dispatchEvent(dragEvent) == false
|
||||
const location = this.locationFromEvent(e)
|
||||
// Do actual actions
|
||||
this.lastLocation = Utility.snapToGrid(this.clickedPosition, this.stepSize)
|
||||
this.startDrag(location)
|
||||
this.started = true
|
||||
}
|
||||
|
||||
#mouseMoveHandler =
|
||||
/** @param {MouseEvent} e */
|
||||
e => {
|
||||
if (this.options.consumeEvent) {
|
||||
e.stopImmediatePropagation() // Captured, don't call anyone else
|
||||
this.#movementListenedElement.removeEventListener("mousemove", this.#mouseMoveHandler)
|
||||
document.removeEventListener("mouseup", this.#mouseUpHandler)
|
||||
if (this.started) {
|
||||
this.endDrag()
|
||||
}
|
||||
const location = this.locationFromEvent(e)
|
||||
const movement = [e.movementX, e.movementY]
|
||||
this.dragTo(location, movement)
|
||||
this.unclicked()
|
||||
if (this.#trackingMouse) {
|
||||
this.blueprint.mousePosition = this.locationFromEvent(e)
|
||||
}
|
||||
}
|
||||
|
||||
#mouseUpHandler =
|
||||
/** @param {MouseEvent} e */
|
||||
e => {
|
||||
if (!this.options.exitAnyButton || e.button == this.options.clickButton) {
|
||||
if (this.options.consumeEvent) {
|
||||
e.stopImmediatePropagation() // Captured, don't call anyone else
|
||||
}
|
||||
// Remove the handlers of "mousemove" and "mouseup"
|
||||
this.#movementListenedElement.removeEventListener("mousemove", this.#mouseStartedMovingHandler)
|
||||
this.#movementListenedElement.removeEventListener("mousemove", this.#mouseMoveHandler)
|
||||
document.removeEventListener("mouseup", this.#mouseUpHandler)
|
||||
if (this.started) {
|
||||
this.endDrag()
|
||||
}
|
||||
this.unclicked()
|
||||
if (this.#trackingMouse) {
|
||||
const dragEvent = this.getEvent(Configuration.trackingMouseEventName.end)
|
||||
this.target.dispatchEvent(dragEvent)
|
||||
this.#trackingMouse = false
|
||||
}
|
||||
this.started = false
|
||||
const dragEvent = this.getEvent(Configuration.trackingMouseEventName.end)
|
||||
this.target.dispatchEvent(dragEvent)
|
||||
this.#trackingMouse = false
|
||||
}
|
||||
this.started = false
|
||||
}
|
||||
}
|
||||
|
||||
#trackingMouse = false
|
||||
#movementListenedElement
|
||||
|
||||
@@ -25,6 +25,6 @@ export default class IPointing extends IInput {
|
||||
)
|
||||
return this.options.ignoreTranslateCompensate
|
||||
? location
|
||||
: this.blueprint.compensateTranslation(location)
|
||||
: this.blueprint.compensateTranslation(location[0], location[1])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,9 @@ export default class MouseClickDrag extends MouseMoveDraggable {
|
||||
}
|
||||
}
|
||||
|
||||
clicked() {
|
||||
super.clicked()
|
||||
/** @param {[Number, Number]} location */
|
||||
clicked(location) {
|
||||
super.clicked(location)
|
||||
this.#onClicked?.()
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ export default class MouseCreateLink extends IMouseClickDrag {
|
||||
this.link.setMessageDirectionsIncompatible()
|
||||
} else if (a.isOutput() == b.isOutput()) {
|
||||
this.link.setMessageDirectionsIncompatible()
|
||||
} else if (this.blueprint.getLinks([a, b]).length) {
|
||||
} else if (this.blueprint.getLinks(a, b).length) {
|
||||
this.link.setMessageReplaceLink()
|
||||
this.linkValid = true
|
||||
} else {
|
||||
|
||||
@@ -12,23 +12,31 @@ import Utility from "../../Utility"
|
||||
*/
|
||||
export default class MouseMoveDraggable extends IMouseClickDrag {
|
||||
|
||||
/** @param {[Number, Number]} location */
|
||||
clicked(location) {
|
||||
if (this.options.repositionOnClick) {
|
||||
this.target.setLocation(this.stepSize > 1
|
||||
? Utility.snapToGrid(location, this.stepSize)
|
||||
this.target.setLocation(...(this.stepSize > 1
|
||||
? Utility.snapToGrid(location[0], location[1], this.stepSize)
|
||||
: location
|
||||
)
|
||||
))
|
||||
this.clickedOffset = [0, 0]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number[]} location
|
||||
* @param {Number[]} offset
|
||||
*/
|
||||
dragTo(location, offset) {
|
||||
const targetLocation = [
|
||||
this.target.locationX ?? this.lastLocation[0],
|
||||
this.target.locationY ?? this.lastLocation[1],
|
||||
]
|
||||
const [adjustedLocation, adjustedTargetLocation] = this.stepSize > 1
|
||||
? [Utility.snapToGrid(location, this.stepSize), Utility.snapToGrid(targetLocation, this.stepSize)]
|
||||
? [
|
||||
Utility.snapToGrid(location[0], location[1], this.stepSize),
|
||||
Utility.snapToGrid(targetLocation[0], targetLocation[1], this.stepSize)
|
||||
]
|
||||
: [location, targetLocation]
|
||||
offset = [
|
||||
adjustedLocation[0] - this.lastLocation[0],
|
||||
@@ -45,10 +53,11 @@ export default class MouseMoveDraggable extends IMouseClickDrag {
|
||||
this.lastLocation = adjustedLocation
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number[]} location
|
||||
* @param {Number[]} offset
|
||||
*/
|
||||
dragAction(location, offset) {
|
||||
this.target.setLocation([
|
||||
location[0] - this.clickedOffset[0],
|
||||
location[1] - this.clickedOffset[1],
|
||||
])
|
||||
this.target.setLocation(location[0] - this.clickedOffset[0], location[1] - this.clickedOffset[1])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ export default class MouseScrollGraph extends IMouseClickDrag {
|
||||
}
|
||||
|
||||
dragTo(location, movement) {
|
||||
this.blueprint.scrollDelta([-movement[0], -movement[1]])
|
||||
this.blueprint.scrollDelta(-movement[0], -movement[1])
|
||||
}
|
||||
|
||||
endDrag() {
|
||||
|
||||
@@ -457,7 +457,7 @@ export default class Grammar {
|
||||
}
|
||||
)
|
||||
|
||||
/** @returns {Parsimmon.Parser<ObjectEntity[]>} */
|
||||
/** @param {Grammar} r */
|
||||
MultipleObject = r => r.Object.sepBy1(P.whitespace).trim(P.optWhitespace)
|
||||
|
||||
/* --- Others --- */
|
||||
|
||||
@@ -3,6 +3,8 @@ import ObjectEntity from "../entity/ObjectEntity"
|
||||
import PinEntity from "../entity/PinEntity"
|
||||
import SerializerFactory from "./SerializerFactory"
|
||||
|
||||
/** @typedef {import("../element/NodeElement").default} NodeElement */
|
||||
|
||||
export default class ObjectSerializer extends ISerializer {
|
||||
|
||||
constructor() {
|
||||
@@ -29,7 +31,10 @@ export default class ObjectSerializer extends ISerializer {
|
||||
return parseResult.value
|
||||
}
|
||||
|
||||
/** @param {String} value */
|
||||
/**
|
||||
* @param {String} value
|
||||
* @returns {NodeElement[]}
|
||||
*/
|
||||
readMultiple(value) {
|
||||
const parseResult = ISerializer.grammar.MultipleObject.parse(value)
|
||||
if (!parseResult.status) {
|
||||
|
||||
@@ -6,13 +6,17 @@ import Utility from "../Utility"
|
||||
/** @extends {IDraggableControlTemplate<ColorHandlerElement>} */
|
||||
export default class ColorHandlerTemplate extends IDraggableControlTemplate {
|
||||
|
||||
/** @param {[Number, Number]} param0 */
|
||||
adjustLocation([x, y]) {
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
* @returns {[Number, Number]}
|
||||
*/
|
||||
adjustLocation(x, y) {
|
||||
const radius = Math.round(this.movementSpaceSize[0] / 2)
|
||||
x = x - radius
|
||||
y = -(y - radius)
|
||||
let [r, theta] = Utility.getPolarCoordinates([x, y])
|
||||
r = Math.min(r, radius), [x, y] = Utility.getCartesianCoordinates([r, theta])
|
||||
let [r, theta] = Utility.getPolarCoordinates(x, y)
|
||||
r = Math.min(r, radius), [x, y] = Utility.getCartesianCoordinates(r, theta)
|
||||
this.locationChangeCallback?.(x / radius, y / radius)
|
||||
x = Math.round(x + radius)
|
||||
y = Math.round(-y + radius)
|
||||
|
||||
@@ -125,7 +125,7 @@ export default class ColorPickerWindowTemplate extends WindowTemplate {
|
||||
* @param {Number} y in the range [0, 1]
|
||||
*/
|
||||
(x, y) => {
|
||||
this.color.setFromWheelLocation([x, y], this.color.V.value, this.color.A.value)
|
||||
this.color.setFromWheelLocation(x, y, this.color.V.value, this.color.A.value)
|
||||
this.fullColor.setFromHSVA(this.color.H.value, 1, 1, 1)
|
||||
this.element.requestUpdate()
|
||||
}
|
||||
|
||||
@@ -6,8 +6,12 @@ import Utility from "../Utility"
|
||||
/** @extends {IDraggableControlTemplate<ColorHandlerElement>} */
|
||||
export default class ColorSliderTemplate extends IDraggableControlTemplate {
|
||||
|
||||
/** @param {[Number, Number]} param0 */
|
||||
adjustLocation([x, y]) {
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
* @return {[Number, Number]}
|
||||
*/
|
||||
adjustLocation(x, y) {
|
||||
x = Utility.clamp(x, 0, this.movementSpaceSize[0])
|
||||
y = Utility.clamp(y, 0, this.movementSpaceSize[1])
|
||||
this.locationChangeCallback?.(x / this.movementSpaceSize[0], 1 - y / this.movementSpaceSize[1])
|
||||
|
||||
@@ -47,8 +47,12 @@ export default class IDraggableControlTemplate extends IDraggableTemplate {
|
||||
})
|
||||
}
|
||||
|
||||
/** @param {[Number, Number]} param0 */
|
||||
adjustLocation([x, y]) {
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
* @returns {[Number, Number]}
|
||||
*/
|
||||
adjustLocation(x, y) {
|
||||
this.locationChangeCallback?.(x, y)
|
||||
return [x, y]
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ export default class IDraggableTemplate extends ITemplate {
|
||||
const dt = this.topBoundary() - this.blueprint.template.gridTopVisibilityBoundary()
|
||||
const db = this.blueprint.template.gridBottomVisibilityBoundary() - this.bottomBoundary()
|
||||
let avgY = Math.max((dt + db) / 2, minMargin)
|
||||
const delta = [dl - avgX, dt - avgY]
|
||||
this.blueprint.scrollDelta(delta, true)
|
||||
this.blueprint.scrollDelta(dl - avgX, dt - avgY, true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ export default class IResizeableTemplate extends NodeTemplate {
|
||||
onDrag: (location, movement) => {
|
||||
movement[1] = location[1] - this.element.topBoundary()
|
||||
if (this.setSizeY(this.element.sizeY - movement[1])) {
|
||||
this.element.addLocation([0, movement[1]], false)
|
||||
this.element.addLocation(0, movement[1], false)
|
||||
}
|
||||
},
|
||||
onEndDrag: () => this.endResize(),
|
||||
@@ -87,7 +87,7 @@ export default class IResizeableTemplate extends NodeTemplate {
|
||||
onDrag: (location, movement) => {
|
||||
movement[0] = location[0] - this.element.leftBoundary()
|
||||
if (this.setSizeX(this.element.sizeX - movement[0])) {
|
||||
this.element.addLocation([movement[0], 0], false)
|
||||
this.element.addLocation(movement[0], 0, false)
|
||||
}
|
||||
},
|
||||
onEndDrag: () => this.endResize(),
|
||||
@@ -98,7 +98,7 @@ export default class IResizeableTemplate extends NodeTemplate {
|
||||
movement[1] = location[1] - this.element.topBoundary()
|
||||
this.setSizeX(this.element.sizeX + movement[0])
|
||||
if (this.setSizeY(this.element.sizeY - movement[1])) {
|
||||
this.element.addLocation([0, movement[1]], false)
|
||||
this.element.addLocation(0, movement[1], false)
|
||||
}
|
||||
},
|
||||
onEndDrag: () => this.endResize(),
|
||||
@@ -117,7 +117,7 @@ export default class IResizeableTemplate extends NodeTemplate {
|
||||
movement[0] = location[0] - this.element.leftBoundary()
|
||||
movement[1] = location[1] - this.element.bottomBoundary()
|
||||
if (this.setSizeX(this.element.sizeX - movement[0])) {
|
||||
this.element.addLocation([movement[0], 0], false)
|
||||
this.element.addLocation(movement[0], 0, false)
|
||||
}
|
||||
this.setSizeY(this.element.sizeY + movement[1])
|
||||
},
|
||||
@@ -128,10 +128,10 @@ export default class IResizeableTemplate extends NodeTemplate {
|
||||
movement[0] = location[0] - this.element.leftBoundary()
|
||||
movement[1] = location[1] - this.element.topBoundary()
|
||||
if (this.setSizeX(this.element.sizeX - movement[0])) {
|
||||
this.element.addLocation([movement[0], 0], false)
|
||||
this.element.addLocation(movement[0], 0, false)
|
||||
}
|
||||
if (this.setSizeY(this.element.sizeY - movement[1])) {
|
||||
this.element.addLocation([0, movement[1]], false)
|
||||
this.element.addLocation(0, movement[1], false)
|
||||
}
|
||||
},
|
||||
onEndDrag: () => this.endResize(),
|
||||
|
||||
@@ -63,12 +63,12 @@ export default class LinkTemplate extends IFromToPositionedTemplate {
|
||||
|
||||
static c2Clamped = LinkTemplate.clampedLine([0, 100], [200, 30])
|
||||
|
||||
/** @type {(location: Number[]) => void} */
|
||||
/** @param {[Number, Number]} location */
|
||||
#createKnot = location => {
|
||||
const knotEntity = new KnotEntity({}, this.element.sourcePin.entity)
|
||||
const knot = /** @type {NodeElementConstructor} */(ElementFactory.getConstructor("ueb-node"))
|
||||
.newObject(knotEntity)
|
||||
knot.setLocation(this.blueprint.snapToGrid(location))
|
||||
knot.setLocation(...this.blueprint.snapToGrid(...location))
|
||||
this.blueprint.addGraphElement(knot) // Important: keep it before changing existing links
|
||||
const link = /** @type {LinkElementConstructor} */(ElementFactory.getConstructor("ueb-link"))
|
||||
.newObject(
|
||||
@@ -86,7 +86,8 @@ export default class LinkTemplate extends IFromToPositionedTemplate {
|
||||
this.element.querySelector(".ueb-link-area"),
|
||||
this.blueprint,
|
||||
undefined,
|
||||
(location) => this.#createKnot(location)
|
||||
/** @param {[Number, Number]} location */
|
||||
location => this.#createKnot(location)
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@ export default class KnotPinTemplate extends PinTemplate {
|
||||
],
|
||||
this.blueprint.template.gridElement
|
||||
)
|
||||
return this.blueprint.compensateTranslation(location)
|
||||
return this.blueprint.compensateTranslation(location[0], location[1])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ export default class PinTemplate extends ITemplate {
|
||||
[(rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2],
|
||||
this.blueprint.template.gridElement
|
||||
)
|
||||
return this.blueprint.compensateTranslation(location)
|
||||
return this.blueprint.compensateTranslation(location[0], location[1])
|
||||
}
|
||||
|
||||
getClickableElement() {
|
||||
|
||||
Reference in New Issue
Block a user