graflow: wireType straight

This commit is contained in:
STEINNI
2026-03-01 13:27:00 +00:00
parent 9bc55b74d6
commit 070be08dee

View File

@@ -85,10 +85,11 @@ class BZgraflow extends Buildoz{
this.mainContainer.append(this.nodesContainer)
this.append(this.hostContainer)
this.loadFlow(flowUrl).then(() => {
if(this.hasAttribute('editable')){
if((this.getBZAttribute('edit')=='move') || (this.getBZAttribute('edit')=='full')){
this.dnd = new MovingNodes(this)
this.dnd.enableMovingNodes('.bzgf-node') }
}) // Let it load async
this.dnd.enableMovingNodes('.bzgf-node')
}
})
}
error(msg, err){
@@ -393,7 +394,7 @@ class BZgraflow extends Buildoz{
addWire(link){
const [idNode1, idPort1] = link.from
const [idNode2, idPort2] = link.to
const path = this.bezierNodes(idNode1, idPort1, idNode2, idPort2, this.getBZAttribute('tension'))
const path = this.linkNodes(idNode1, idPort1, idNode2, idPort2)
const id = `${idNode1}_${idNode2}`
this.stagedWires[id] = document.createElementNS('http://www.w3.org/2000/svg', 'path')
this.stagedWires[id].setAttribute('d', path)
@@ -458,8 +459,9 @@ class BZgraflow extends Buildoz{
return({ x: x - r.left, y: y - r.top })
}
bezierNodes(idNode1, idPort1, idNode2, idPort2, tension=60) {
tension = parseInt(tension)
linkNodes(idNode1, idPort1, idNode2, idPort2) {
const tension = parseInt(this.getBZAttribute('tension')) || 60
const wireType = this.getBZAttribute('wiretype') || 'bezier'
const node1 = this.stagedNodes[idNode1]
const port1 = node1.ports[idPort1]
const node2 = this.stagedNodes[idNode2]
@@ -477,7 +479,6 @@ class BZgraflow extends Buildoz{
const x2 = Math.floor(p2.x)
const y2 = Math.floor(p2.y)
const loop = (idNode1==idNode2) && (idPort1==idPort2)
const dist = Math.abs(x2 - x1) + Math.abs(y2 - y1)
let c1x = Math.floor(x1 + (this.dirVect[port1.direction].x * tension))
let c1y = Math.floor(y1 + (this.dirVect[port1.direction].y * tension))
@@ -492,42 +493,69 @@ class BZgraflow extends Buildoz{
c1y += 1*tension
c2y -= 1*tension
}
}
return(`M ${x1} ${y1} C ${c1x} ${c1y}, ${c2x} ${c2y}, ${x2} ${y2}`)
}
if(wireType === 'bezier') {
return(`M ${x1} ${y1} C ${c1x} ${c1y}, ${c2x} ${c2y}, ${x2} ${y2}`)
}
if(wireType === 'straight') {
console.log('straight')
// Straight segments through the same control points
return(`M ${x1} ${y1} L ${c1x} ${c1y} L ${c2x} ${c2y} L ${x2} ${y2}`)
}
return('')
//return(`M ${x1} ${y1} C ${c1x} ${c1y}, ${c2x} ${c2y}, ${x2} ${y2}`)
}
bezierInterNodes(idNode1, idPort1, idNode2, idPort2, interNodes, orientation='horizontal', tension=60) {
tension = parseInt(tension)
linkInterNodes(idNode1, idPort1, idNode2, idPort2, interNodes, orientation='horizontal') {
const tension = parseInt(this.getBZAttribute('tension')) || 60
const wireType = this.getBZAttribute('wiretype') || 'bezier'
const node1 = this.stagedNodes[idNode1]
let port1 = node1.ports[idPort1]
const port1 = node1.ports[idPort1]
const node2 = this.stagedNodes[idNode2]
const port2 = node2.ports[idPort2]
if(!node1 || !node2 || !port1 || !port2) {
console.warn('Link on bad node / port ', idNode1, idPort1, idNode2, idPort2)
return('')
}
const makeCubicBezier = (x1, y1, x2, y2, orientation1, orientation2) => {
const dist = Math.abs(x2 - x1) + Math.abs(y2 - y1)
let c1x, c1y, c2x, c2y
if(orientation1=='horizontal'){
const makeSegment = (x1, y1, x2, y2, orientation1, orientation2) => {
let c1x, c1y, c2x, c2y
if(orientation1=='horizontal') {
c1x = Math.floor(x1 + tension)
c1y = y1
} else {
c1x = x1
c1y = Math.floor(y1 + tension)
}
if(orientation2=='horizontal'){
if(orientation2=='horizontal') {
c2x = Math.floor(x2 - tension)
c2y = y2
} else {
c2x = x2
c2y = Math.floor(y2 - tension)
}
if(wireType === 'bezier') {
return(`C ${c1x} ${c1y}, ${c2x} ${c2y}, ${x2} ${y2}`)
}
if(wireType === 'straight') {
return(`L ${c1x} ${c1y} L ${c2x} ${c2y} L ${x2} ${y2}`)
}
return(`C ${c1x} ${c1y}, ${c2x} ${c2y}, ${x2} ${y2}`)
}
const directPath = this.bezierNodes(idNode1, idPort1, idNode2, idPort2, tension)
const startPath = directPath.substring(0,directPath.indexOf('C'))
const endPath = directPath.substring(directPath.lastIndexOf(',')+1).trim()
let path = startPath
let [ , x1, y1] = startPath.split(' ')
x1 = parseFloat(x1)
y1 = parseFloat(y1)
// Start/end points in SVG coords (works for both bezier and line)
const bb1 = port1.el.getBoundingClientRect()
const bb2 = port2.el.getBoundingClientRect()
const sp = this.clientToSvg(bb1.x + (bb1.width/2), bb1.y + (bb1.height/2))
const ep = this.clientToSvg(bb2.x + (bb2.width/2), bb2.y + (bb2.height/2))
let x1 = Math.floor(sp.x)
let y1 = Math.floor(sp.y)
const xEnd = Math.floor(ep.x)
const yEnd = Math.floor(ep.y)
let path = `M ${x1} ${y1} `
let firstPort = port1
for(const interNode of interNodes){
const bb = this.stagedNodes[interNode].getBoundingClientRect()
// Entry/exit points on the placeholder box, converted to SVG coords (handles CSS transforms)
@@ -544,11 +572,11 @@ class BZgraflow extends Buildoz{
let x2 = Math.floor(entry.x)
let y2 = Math.floor(entry.y)
if(port1){
path += makeCubicBezier(x1, y1, x2, y2, ['w','e'].includes(port1.direction) ? 'horizontal' : 'vertical', orientation)
port1 = false
if(firstPort){
path += makeSegment(x1, y1, x2, y2, ['w','e'].includes(firstPort.direction) ? 'horizontal' : 'vertical', orientation)
firstPort = null
} else {
path += makeCubicBezier(x1, y1, x2, y2, orientation, orientation)
path += makeSegment(x1, y1, x2, y2, orientation, orientation)
}
const x3 = Math.floor(exit.x)
@@ -558,10 +586,7 @@ class BZgraflow extends Buildoz{
x1 = x3
y1 = y3
}
let [x2, y2] = endPath.split(' ')
x2 = parseFloat(x2)
y2 = parseFloat(y2)
path += ' '+makeCubicBezier(x1, y1, x2, y2, orientation, orientation)
path += ' ' + makeSegment(x1, y1, xEnd, yEnd, orientation, orientation)
return(path)
}
@@ -574,12 +599,7 @@ class BZgraflow extends Buildoz{
// Cleanup placeholders from previous autoPlace() runs.
// Each run creates new longLinkPlaceHolder_* IDs; without cleanup they accumulate in the DOM.
for(const nid of Object.keys(this.stagedNodes || {})){
if(!nid.startsWith('longLinkPlaceHolder_')) continue
const el = this.stagedNodes[nid]
if(el?.parentNode) el.parentNode.removeChild(el)
delete this.stagedNodes[nid]
}
this.clearFakeNodes()
// Loops create infinite recursion in dfs for getting parents & adjacency lists: Remove them !
let linksWithoutBackEdges
@@ -724,6 +744,15 @@ class BZgraflow extends Buildoz{
}
}
clearFakeNodes(){
for(const nid of Object.keys(this.stagedNodes || {})){
if(!nid.startsWith('longLinkPlaceHolder_')) continue
const el = this.stagedNodes[nid]
if(el?.parentNode) el.parentNode.removeChild(el)
delete this.stagedNodes[nid]
}
}
getMaxWidth(layer){
return(layer.filter(nid =>
!nid.startsWith('longLinkPlaceHolder_'))
@@ -849,7 +878,7 @@ class BZgraflow extends Buildoz{
const y = y0 + (desty - y0) * k
el.style.left = `${x}px`
el.style.top = `${y}px`
this.updateWires(nid, orientation)
this.updateWires(nid, orientation, true)
if(p < 1) requestAnimationFrame(frame.bind(this))
else{
@@ -863,7 +892,7 @@ class BZgraflow extends Buildoz{
requestAnimationFrame(frame.bind(this))
}
updateWires(nid, orientation){
updateWires(nid, orientation, LondLinkfix = false){
const wires = Object.keys(this.stagedWires)
.filter(id => (id.startsWith(nid+'_')||id.endsWith('_'+nid)))
.map(id => this.stagedWires[id])
@@ -873,11 +902,11 @@ class BZgraflow extends Buildoz{
if(!lnk) continue
if(!this.flow?.longLinks) this.flow.longLinks = []
const longLink = this.flow.longLinks.find(item => (item.link.from[0] == lnk.from[0] && item.link.from[1] == lnk.from[1] && item.link.to[0] == lnk.to[0] && item.link.to[1] == lnk.to[1]))
if(longLink) {
const path = this.bezierInterNodes(nid1, lnk.from[1], nid2, lnk.to[1], longLink.interNodes, orientation, this.getBZAttribute('tension'))
if(longLink && LondLinkfix) {
const path = this.linkInterNodes(nid1, lnk.from[1], nid2, lnk.to[1], longLink.interNodes, orientation)
wire.setAttribute('d', path)
} else {
const path = this.bezierNodes(nid1, lnk.from[1], nid2, lnk.to[1], this.getBZAttribute('tension'))
const path = this.linkNodes(nid1, lnk.from[1], nid2, lnk.to[1])
wire.setAttribute('d', path)
}
}
@@ -1051,6 +1080,7 @@ class MovingNodes{
}
pointerDown(e){
this.graflow.clearFakeNodes()
const node = (e.target.classList.contains(this.itemSelector)) ? e.target : e.target.closest(this.itemSelector)
const handle = (node.classList.contains(this.handleSelector)) ? node : node.querySelector(this.handleSelector)
@@ -1081,7 +1111,7 @@ class MovingNodes{
const y = e.clientY - startY + offsetY
node.style.left = `${x}px`
node.style.top = `${y}px`
this.graflow.updateWires(node.dataset.id, this.graflow.currentOrientation)
this.graflow.updateWires(node.dataset.id, this.graflow.currentOrientation, false)
}
pointerUp(e){