@flowgram.ai/free-layout-core 0.1.0-alpha.35 → 0.1.0-alpha.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/index.js +472 -62
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +462 -52
- package/dist/index.js.map +1 -1
- package/dist/typings/index.d.mts +1 -1
- package/dist/typings/index.d.ts +1 -1
- package/dist/typings/workflow-drag.d.mts +1 -1
- package/dist/typings/workflow-drag.d.ts +1 -1
- package/dist/typings/workflow-json.d.mts +1 -1
- package/dist/typings/workflow-json.d.ts +1 -1
- package/dist/typings/workflow-line.d.mts +1 -1
- package/dist/typings/workflow-line.d.ts +1 -1
- package/dist/typings/workflow-node.d.mts +1 -1
- package/dist/typings/workflow-node.d.ts +1 -1
- package/dist/typings/workflow-operation.d.mts +1 -1
- package/dist/typings/workflow-operation.d.ts +1 -1
- package/dist/typings/workflow-registry.d.mts +1 -1
- package/dist/typings/workflow-registry.d.ts +1 -1
- package/dist/typings/workflow-sub-canvas.d.mts +1 -1
- package/dist/typings/workflow-sub-canvas.d.ts +1 -1
- package/dist/{workflow-node-entity-C6bFzfXc.d.mts → workflow-node-entity-BQBXdOoa.d.mts} +46 -2
- package/dist/{workflow-node-entity-03Q7Fvv6.d.ts → workflow-node-entity-Da9FrkWn.d.ts} +46 -2
- package/package.json +9 -9
package/dist/esm/index.js
CHANGED
|
@@ -318,7 +318,14 @@ var WorkflowPortEntity = class extends Entity {
|
|
|
318
318
|
);
|
|
319
319
|
}
|
|
320
320
|
isHovered(x, y) {
|
|
321
|
-
|
|
321
|
+
const { point } = this;
|
|
322
|
+
const size = this._size || { width: PORT_SIZE, height: PORT_SIZE };
|
|
323
|
+
const halfWidth = size.width / 2;
|
|
324
|
+
const halfHeight = size.height / 2;
|
|
325
|
+
if (size.width <= 0 || size.height <= 0) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
return x >= point.x - halfWidth && x <= point.x + halfWidth && y >= point.y - halfHeight && y <= point.y + halfHeight;
|
|
322
329
|
}
|
|
323
330
|
/**
|
|
324
331
|
* 相对节点左上角的位置
|
|
@@ -419,6 +426,7 @@ var WorkflowNodePortsData = class extends EntityData {
|
|
|
419
426
|
this._staticPorts = [];
|
|
420
427
|
/** 存储 port 实体的 id,用于判断 port 是否存在 */
|
|
421
428
|
this._portIDSet = /* @__PURE__ */ new Set();
|
|
429
|
+
this._portDisposeIDSet = /* @__PURE__ */ new Set();
|
|
422
430
|
this.entity = entity;
|
|
423
431
|
const meta = entity.getNodeMeta();
|
|
424
432
|
const defaultPorts = meta.useDynamicPort ? [] : [{ type: "input" }, { type: "output" }];
|
|
@@ -505,6 +513,7 @@ var WorkflowNodePortsData = class extends EntityData {
|
|
|
505
513
|
});
|
|
506
514
|
ports.forEach((port) => this.updatePortEntity(port));
|
|
507
515
|
this._prePorts = ports;
|
|
516
|
+
this.clearPortsCache();
|
|
508
517
|
this.fireChange();
|
|
509
518
|
}
|
|
510
519
|
this.allPorts.forEach((port) => {
|
|
@@ -517,19 +526,28 @@ var WorkflowNodePortsData = class extends EntityData {
|
|
|
517
526
|
* 获取所有 port entities
|
|
518
527
|
*/
|
|
519
528
|
get allPorts() {
|
|
520
|
-
|
|
529
|
+
if (!this._allPortsCache) {
|
|
530
|
+
this._allPortsCache = Array.from(this._portIDSet).map((portId) => this.getPortEntity(portId)).filter(Boolean);
|
|
531
|
+
}
|
|
532
|
+
return this._allPortsCache;
|
|
521
533
|
}
|
|
522
534
|
/**
|
|
523
535
|
* 获取输入点位
|
|
524
536
|
*/
|
|
525
537
|
get inputPorts() {
|
|
526
|
-
|
|
538
|
+
if (!this._inputPortsCache) {
|
|
539
|
+
this._inputPortsCache = this.allPorts.filter((port) => port.portType === "input");
|
|
540
|
+
}
|
|
541
|
+
return this._inputPortsCache;
|
|
527
542
|
}
|
|
528
543
|
/**
|
|
529
544
|
* 获取输出点位
|
|
530
545
|
*/
|
|
531
546
|
get outputPorts() {
|
|
532
|
-
|
|
547
|
+
if (!this._outputPortsCache) {
|
|
548
|
+
this._outputPortsCache = this.allPorts.filter((port) => port.portType === "output");
|
|
549
|
+
}
|
|
550
|
+
return this._outputPortsCache;
|
|
533
551
|
}
|
|
534
552
|
/**
|
|
535
553
|
* 获取输入点位置
|
|
@@ -541,7 +559,7 @@ var WorkflowNodePortsData = class extends EntityData {
|
|
|
541
559
|
* 获取输出点位置
|
|
542
560
|
*/
|
|
543
561
|
get outputPoints() {
|
|
544
|
-
return this.
|
|
562
|
+
return this.outputPorts.map((port) => port.point);
|
|
545
563
|
}
|
|
546
564
|
/**
|
|
547
565
|
* 根据 key 获取 输入点位置
|
|
@@ -570,6 +588,11 @@ var WorkflowNodePortsData = class extends EntityData {
|
|
|
570
588
|
getPortId(portType, portKey = "") {
|
|
571
589
|
return getPortEntityId(this.entity, portType, portKey);
|
|
572
590
|
}
|
|
591
|
+
clearPortsCache() {
|
|
592
|
+
this._allPortsCache = void 0;
|
|
593
|
+
this._inputPortsCache = void 0;
|
|
594
|
+
this._outputPortsCache = void 0;
|
|
595
|
+
}
|
|
573
596
|
/**
|
|
574
597
|
* 创建 port 实体
|
|
575
598
|
*/
|
|
@@ -583,10 +606,18 @@ var WorkflowNodePortsData = class extends EntityData {
|
|
|
583
606
|
...portInfo
|
|
584
607
|
});
|
|
585
608
|
}
|
|
586
|
-
|
|
587
|
-
this.
|
|
588
|
-
|
|
589
|
-
|
|
609
|
+
if (!this._portDisposeIDSet.has(id)) {
|
|
610
|
+
this._portDisposeIDSet.add(id);
|
|
611
|
+
portEntity.onDispose(() => {
|
|
612
|
+
this._portIDSet.delete(id);
|
|
613
|
+
this._portDisposeIDSet.delete(id);
|
|
614
|
+
this.clearPortsCache();
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
if (!this._portIDSet.has(id)) {
|
|
618
|
+
this._portIDSet.add(id);
|
|
619
|
+
this.clearPortsCache();
|
|
620
|
+
}
|
|
590
621
|
return portEntity;
|
|
591
622
|
}
|
|
592
623
|
/**
|
|
@@ -1448,7 +1479,7 @@ import {
|
|
|
1448
1479
|
Point
|
|
1449
1480
|
} from "@flowgram.ai/utils";
|
|
1450
1481
|
import { FlowNodeTransformData as FlowNodeTransformData6 } from "@flowgram.ai/document";
|
|
1451
|
-
import { FlowNodeBaseType as
|
|
1482
|
+
import { FlowNodeBaseType as FlowNodeBaseType4 } from "@flowgram.ai/document";
|
|
1452
1483
|
import {
|
|
1453
1484
|
CommandService,
|
|
1454
1485
|
MouseTouchEvent,
|
|
@@ -1458,10 +1489,9 @@ import {
|
|
|
1458
1489
|
} from "@flowgram.ai/core";
|
|
1459
1490
|
|
|
1460
1491
|
// src/workflow-lines-manager.ts
|
|
1461
|
-
import { last } from "lodash-es";
|
|
1462
1492
|
import { inject as inject3, injectable as injectable3 } from "inversify";
|
|
1463
1493
|
import { DisposableCollection, Emitter as Emitter4 } from "@flowgram.ai/utils";
|
|
1464
|
-
import { FlowNodeRenderData as FlowNodeRenderData2, FlowNodeTransformData as FlowNodeTransformData3 } from "@flowgram.ai/document";
|
|
1494
|
+
import { FlowNodeBaseType as FlowNodeBaseType2, FlowNodeRenderData as FlowNodeRenderData2, FlowNodeTransformData as FlowNodeTransformData3 } from "@flowgram.ai/document";
|
|
1465
1495
|
import { EntityManager as EntityManager2, PlaygroundConfigEntity as PlaygroundConfigEntity2 } from "@flowgram.ai/core";
|
|
1466
1496
|
|
|
1467
1497
|
// src/workflow-document-option.ts
|
|
@@ -1540,6 +1570,12 @@ var WorkflowDocumentOptionsDefault = {
|
|
|
1540
1570
|
};
|
|
1541
1571
|
|
|
1542
1572
|
// src/workflow-lines-manager.ts
|
|
1573
|
+
var NODE_HIT_CELL_SIZE = 512;
|
|
1574
|
+
var LINE_HIT_CELL_SIZE = 512;
|
|
1575
|
+
var PORT_NODE_BOUNDS_PADDING = 96;
|
|
1576
|
+
var NODE_INDEX_MIN_SIZE = 128;
|
|
1577
|
+
var LINE_INDEX_MIN_SIZE = 128;
|
|
1578
|
+
var MAX_SPATIAL_CELLS_PER_ITEM = 64;
|
|
1543
1579
|
var WorkflowLinesManager = class {
|
|
1544
1580
|
constructor() {
|
|
1545
1581
|
this.toDispose = new DisposableCollection();
|
|
@@ -1563,11 +1599,35 @@ var WorkflowLinesManager = class {
|
|
|
1563
1599
|
this.isDrawing = false;
|
|
1564
1600
|
}
|
|
1565
1601
|
init(doc) {
|
|
1602
|
+
if (this.document === doc) {
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1566
1605
|
this.document = doc;
|
|
1606
|
+
this.toDispose.pushAll([
|
|
1607
|
+
this.entityManager.onEntityChange((entityType) => {
|
|
1608
|
+
if (entityType === WorkflowNodeEntity.type) {
|
|
1609
|
+
this.invalidateNodeHitCaches();
|
|
1610
|
+
}
|
|
1611
|
+
if (entityType === WorkflowLineEntity.type || entityType === WorkflowPortEntity.type) {
|
|
1612
|
+
this.invalidateLineHitCache();
|
|
1613
|
+
this.outsidePortNodesCache = void 0;
|
|
1614
|
+
}
|
|
1615
|
+
}),
|
|
1616
|
+
this.entityManager.onEntityDataChange(({ entityDataType }) => {
|
|
1617
|
+
if (entityDataType === FlowNodeTransformData3.type) {
|
|
1618
|
+
this.invalidateSpatialHitCaches();
|
|
1619
|
+
}
|
|
1620
|
+
})
|
|
1621
|
+
]);
|
|
1567
1622
|
}
|
|
1568
1623
|
forceUpdate() {
|
|
1569
1624
|
this.onForceUpdateEmitter.fire();
|
|
1570
1625
|
}
|
|
1626
|
+
invalidateSortedNodesCache() {
|
|
1627
|
+
this.sortedNodesCache = void 0;
|
|
1628
|
+
this.sortedNodesCacheVersion = void 0;
|
|
1629
|
+
this.invalidateNodeHitCaches();
|
|
1630
|
+
}
|
|
1571
1631
|
get lineType() {
|
|
1572
1632
|
return this._lineType;
|
|
1573
1633
|
}
|
|
@@ -1596,6 +1656,7 @@ var WorkflowLinesManager = class {
|
|
|
1596
1656
|
}
|
|
1597
1657
|
if (newType !== this._lineType) {
|
|
1598
1658
|
this._lineType = newType;
|
|
1659
|
+
this.lineSpatialCache = void 0;
|
|
1599
1660
|
this.getAllLines().forEach((line) => {
|
|
1600
1661
|
line.getData(WorkflowLineRenderData).update();
|
|
1601
1662
|
});
|
|
@@ -1754,17 +1815,26 @@ var WorkflowLinesManager = class {
|
|
|
1754
1815
|
*/
|
|
1755
1816
|
getCloseInLineFromMousePos(mousePos, minDistance = LINE_HOVER_DISTANCE) {
|
|
1756
1817
|
let targetLine, targetLineDist;
|
|
1757
|
-
this.
|
|
1818
|
+
const lines = this.getLineHitCandidates(mousePos, minDistance);
|
|
1819
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1820
|
+
const line = lines[i];
|
|
1821
|
+
if (!this.isPointInBounds(mousePos, line.bounds, minDistance)) {
|
|
1822
|
+
continue;
|
|
1823
|
+
}
|
|
1758
1824
|
const dist = line.getHoverDist(mousePos);
|
|
1759
|
-
if (dist <= minDistance && (
|
|
1825
|
+
if (dist <= minDistance && (targetLineDist === void 0 || targetLineDist >= dist)) {
|
|
1760
1826
|
targetLineDist = dist;
|
|
1761
1827
|
targetLine = line;
|
|
1762
1828
|
}
|
|
1763
|
-
}
|
|
1829
|
+
}
|
|
1764
1830
|
return targetLine;
|
|
1765
1831
|
}
|
|
1766
1832
|
dispose() {
|
|
1767
1833
|
this.portLineMap.clear();
|
|
1834
|
+
this.sortedNodeSpatialCache = void 0;
|
|
1835
|
+
this.hoverNodeSpatialCache = void 0;
|
|
1836
|
+
this.lineSpatialCache = void 0;
|
|
1837
|
+
this.outsidePortNodesCache = void 0;
|
|
1768
1838
|
this.toDispose.dispose();
|
|
1769
1839
|
}
|
|
1770
1840
|
get disposed() {
|
|
@@ -1879,39 +1949,45 @@ var WorkflowLinesManager = class {
|
|
|
1879
1949
|
* @param pos
|
|
1880
1950
|
*/
|
|
1881
1951
|
getPortFromMousePos(pos, portType) {
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1952
|
+
return this.getHoveredPortFromSortedNodes(pos, this.getSortedNodes(), portType);
|
|
1953
|
+
}
|
|
1954
|
+
getPortsFromMousePos(pos) {
|
|
1955
|
+
return this.getHoveredPortsFromSortedNodes(pos, this.getSortedNodes(), void 0, {
|
|
1956
|
+
collectBoth: true
|
|
1957
|
+
});
|
|
1958
|
+
}
|
|
1959
|
+
getNodeAndPortFromMousePos(pos, portType) {
|
|
1960
|
+
const sortedNodes = this.getSortedNodes();
|
|
1961
|
+
const nodeHitInfo = this.getNodeHitInfoFromSortedNodes(
|
|
1962
|
+
pos,
|
|
1963
|
+
sortedNodes,
|
|
1964
|
+
this.selectService.selection
|
|
1965
|
+
);
|
|
1966
|
+
const ports = this.getHoveredPortsFromSortedNodes(pos, sortedNodes, portType, {
|
|
1967
|
+
topCoverNode: nodeHitInfo.topCoverNode
|
|
1968
|
+
});
|
|
1969
|
+
return {
|
|
1970
|
+
node: nodeHitInfo.topNode,
|
|
1971
|
+
port: ports.port
|
|
1972
|
+
};
|
|
1973
|
+
}
|
|
1974
|
+
getHoverNodeFromMousePos(pos) {
|
|
1975
|
+
const nodes = this.getHoverNodes();
|
|
1976
|
+
const candidates = this.getHoverNodeHitCandidates(pos, nodes);
|
|
1977
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
1978
|
+
const node = candidates[i];
|
|
1979
|
+
const { bounds } = node.getData(FlowNodeTransformData3);
|
|
1980
|
+
if (this.isPointInBounds(pos, bounds)) {
|
|
1981
|
+
return node;
|
|
1895
1982
|
}
|
|
1896
1983
|
}
|
|
1897
|
-
return targetPort;
|
|
1898
1984
|
}
|
|
1899
1985
|
/**
|
|
1900
1986
|
* 根据鼠标位置找到 node
|
|
1901
1987
|
* @param pos - 鼠标位置
|
|
1902
1988
|
*/
|
|
1903
1989
|
getNodeFromMousePos(pos) {
|
|
1904
|
-
|
|
1905
|
-
const containNodes = this.getContainNodesFromMousePos(pos);
|
|
1906
|
-
if (selection?.length) {
|
|
1907
|
-
const filteredNodes = containNodes.filter(
|
|
1908
|
-
(node) => selection.some((_node) => node.id === _node.id)
|
|
1909
|
-
);
|
|
1910
|
-
if (filteredNodes?.length) {
|
|
1911
|
-
return last(filteredNodes);
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
return last(containNodes);
|
|
1990
|
+
return this.getTopNodeFromSortedNodes(pos, this.getSortedNodes(), this.selectService.selection);
|
|
1915
1991
|
}
|
|
1916
1992
|
registerContribution(factory) {
|
|
1917
1993
|
this.contributionFactories.push(factory);
|
|
@@ -1921,19 +1997,352 @@ var WorkflowLinesManager = class {
|
|
|
1921
1997
|
line.addData(WorkflowLineRenderData);
|
|
1922
1998
|
}
|
|
1923
1999
|
getSortedNodes() {
|
|
1924
|
-
|
|
2000
|
+
const nodeVersion = this.entityManager.getEntityVersion(WorkflowNodeEntity);
|
|
2001
|
+
if (this.sortedNodesCache && this.sortedNodesCacheVersion === nodeVersion) {
|
|
2002
|
+
return this.sortedNodesCache;
|
|
2003
|
+
}
|
|
2004
|
+
this.sortedNodesCache = [...this.document.getAllNodes()].sort(
|
|
2005
|
+
(a, b) => this.getNodeIndex(a) - this.getNodeIndex(b)
|
|
2006
|
+
);
|
|
2007
|
+
this.sortedNodesCacheVersion = nodeVersion;
|
|
2008
|
+
this.sortedNodeSpatialCache = void 0;
|
|
2009
|
+
this.outsidePortNodesCache = void 0;
|
|
2010
|
+
return this.sortedNodesCache;
|
|
2011
|
+
}
|
|
2012
|
+
invalidateNodeHitCaches() {
|
|
2013
|
+
this.sortedNodeSpatialCache = void 0;
|
|
2014
|
+
this.hoverNodeSpatialCache = void 0;
|
|
2015
|
+
this.outsidePortNodesCache = void 0;
|
|
2016
|
+
}
|
|
2017
|
+
invalidateLineHitCache() {
|
|
2018
|
+
this.lineSpatialCache = void 0;
|
|
2019
|
+
}
|
|
2020
|
+
invalidateSpatialHitCaches() {
|
|
2021
|
+
this.invalidateNodeHitCaches();
|
|
2022
|
+
this.invalidateLineHitCache();
|
|
2023
|
+
}
|
|
2024
|
+
getHoveredPortFromSortedNodes(pos, sortedNodes, portType) {
|
|
2025
|
+
return this.getHoveredPortsFromSortedNodes(pos, sortedNodes, portType).port;
|
|
2026
|
+
}
|
|
2027
|
+
getHoveredPortsFromSortedNodes(pos, sortedNodes, portType, options = {}) {
|
|
2028
|
+
let inputPort;
|
|
2029
|
+
let outputPort;
|
|
2030
|
+
let anyPort;
|
|
2031
|
+
const { collectBoth = false } = options;
|
|
2032
|
+
const needInput = !portType || portType === "input";
|
|
2033
|
+
const needOutput = !portType || portType === "output";
|
|
2034
|
+
const needAny = !portType && !collectBoth;
|
|
2035
|
+
const candidates = this.getSortedNodeHitCandidates(pos, sortedNodes, PORT_NODE_BOUNDS_PADDING);
|
|
2036
|
+
const checkedNodes = candidates.length === sortedNodes.length ? void 0 : new Set(candidates);
|
|
2037
|
+
for (let i = candidates.length - 1; i >= 0; i--) {
|
|
2038
|
+
const node = candidates[i];
|
|
2039
|
+
if (!this.isPointNearNodePorts(pos, node)) {
|
|
2040
|
+
continue;
|
|
2041
|
+
}
|
|
2042
|
+
const result = this.collectHoveredPorts(node.ports.allPorts, pos, {
|
|
2043
|
+
needInput,
|
|
2044
|
+
needOutput,
|
|
2045
|
+
needAny,
|
|
2046
|
+
inputPort,
|
|
2047
|
+
outputPort,
|
|
2048
|
+
anyPort
|
|
2049
|
+
});
|
|
2050
|
+
inputPort = result.inputPort;
|
|
2051
|
+
outputPort = result.outputPort;
|
|
2052
|
+
anyPort = result.anyPort;
|
|
2053
|
+
if (portType === "input" && inputPort || portType === "output" && outputPort || !portType && (collectBoth ? inputPort && outputPort : anyPort)) {
|
|
2054
|
+
break;
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
if (checkedNodes && !(portType === "input" && inputPort || portType === "output" && outputPort || !portType && (collectBoth ? inputPort && outputPort : anyPort))) {
|
|
2058
|
+
const outsidePortNodes = this.getOutsidePortNodes(sortedNodes);
|
|
2059
|
+
for (let i = outsidePortNodes.length - 1; i >= 0; i--) {
|
|
2060
|
+
const node = outsidePortNodes[i];
|
|
2061
|
+
if (checkedNodes.has(node)) {
|
|
2062
|
+
continue;
|
|
2063
|
+
}
|
|
2064
|
+
const result = this.collectHoveredPorts(node.ports.allPorts, pos, {
|
|
2065
|
+
needInput,
|
|
2066
|
+
needOutput,
|
|
2067
|
+
needAny,
|
|
2068
|
+
inputPort,
|
|
2069
|
+
outputPort,
|
|
2070
|
+
anyPort
|
|
2071
|
+
});
|
|
2072
|
+
inputPort = result.inputPort;
|
|
2073
|
+
outputPort = result.outputPort;
|
|
2074
|
+
anyPort = result.anyPort;
|
|
2075
|
+
if (portType === "input" && inputPort || portType === "output" && outputPort || !portType && (collectBoth ? inputPort && outputPort : anyPort)) {
|
|
2076
|
+
break;
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
const needCoverCheck = inputPort || outputPort || anyPort;
|
|
2081
|
+
const topCoverNode = needCoverCheck ? options.topCoverNode || this.getNodeHitInfoFromSortedNodes(pos, sortedNodes).topCoverNode : void 0;
|
|
2082
|
+
inputPort = this.filterCoveredPort(inputPort, topCoverNode);
|
|
2083
|
+
outputPort = this.filterCoveredPort(outputPort, topCoverNode);
|
|
2084
|
+
anyPort = this.filterCoveredPort(anyPort, topCoverNode);
|
|
2085
|
+
return {
|
|
2086
|
+
input: inputPort,
|
|
2087
|
+
output: outputPort,
|
|
2088
|
+
port: portType === "input" ? inputPort : portType === "output" ? outputPort : anyPort
|
|
2089
|
+
};
|
|
1925
2090
|
}
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
2091
|
+
collectHoveredPorts(ports, pos, options) {
|
|
2092
|
+
let { inputPort, outputPort, anyPort } = options;
|
|
2093
|
+
for (let i = 0; i < ports.length; i++) {
|
|
2094
|
+
const port = ports[i];
|
|
2095
|
+
if ((!options.needAny || anyPort) && (!options.needInput || inputPort) && (!options.needOutput || outputPort)) {
|
|
2096
|
+
break;
|
|
2097
|
+
}
|
|
2098
|
+
if (port.isHovered(pos.x, pos.y)) {
|
|
2099
|
+
if (!anyPort && options.needAny) {
|
|
2100
|
+
anyPort = port;
|
|
2101
|
+
}
|
|
2102
|
+
if (!inputPort && options.needInput && port.portType === "input") {
|
|
2103
|
+
inputPort = port;
|
|
2104
|
+
}
|
|
2105
|
+
if (!outputPort && options.needOutput && port.portType === "output") {
|
|
2106
|
+
outputPort = port;
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
2110
|
+
return {
|
|
2111
|
+
inputPort,
|
|
2112
|
+
outputPort,
|
|
2113
|
+
anyPort
|
|
2114
|
+
};
|
|
2115
|
+
}
|
|
2116
|
+
filterCoveredPort(port, topCoverNode) {
|
|
2117
|
+
if (port && topCoverNode && topCoverNode !== port.node) {
|
|
2118
|
+
return void 0;
|
|
2119
|
+
}
|
|
2120
|
+
return port;
|
|
2121
|
+
}
|
|
2122
|
+
getTopNodeFromSortedNodes(pos, sortedNodes, selection) {
|
|
2123
|
+
return this.getNodeHitInfoFromSortedNodes(pos, sortedNodes, selection).topNode;
|
|
2124
|
+
}
|
|
2125
|
+
getNodeHitInfoFromSortedNodes(pos, sortedNodes, selection) {
|
|
1929
2126
|
const zoom = this.entityManager.getEntity(PlaygroundConfigEntity2)?.config?.zoom || 1;
|
|
1930
|
-
const
|
|
2127
|
+
const padding = 4 / zoom;
|
|
2128
|
+
const selectedIDs = selection?.length ? new Set(selection.map((node) => node.id)) : void 0;
|
|
2129
|
+
const candidates = this.getSortedNodeHitCandidates(pos, sortedNodes, padding);
|
|
2130
|
+
let topCoverNode;
|
|
2131
|
+
for (let i = candidates.length - 1; i >= 0; i--) {
|
|
2132
|
+
const node = candidates[i];
|
|
1931
2133
|
const { bounds } = node.getData(FlowNodeTransformData3);
|
|
1932
|
-
if (
|
|
1933
|
-
|
|
2134
|
+
if (!this.isPointInBounds(pos, bounds, padding)) {
|
|
2135
|
+
continue;
|
|
1934
2136
|
}
|
|
1935
|
-
|
|
1936
|
-
|
|
2137
|
+
if (!topCoverNode) {
|
|
2138
|
+
topCoverNode = node;
|
|
2139
|
+
}
|
|
2140
|
+
if (!selectedIDs) {
|
|
2141
|
+
return {
|
|
2142
|
+
topCoverNode,
|
|
2143
|
+
topNode: node
|
|
2144
|
+
};
|
|
2145
|
+
}
|
|
2146
|
+
if (selectedIDs.has(node.id)) {
|
|
2147
|
+
return {
|
|
2148
|
+
topCoverNode,
|
|
2149
|
+
topNode: node
|
|
2150
|
+
};
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
return {
|
|
2154
|
+
topCoverNode,
|
|
2155
|
+
topNode: topCoverNode
|
|
2156
|
+
};
|
|
2157
|
+
}
|
|
2158
|
+
getHoverNodeHitCandidates(pos, nodes) {
|
|
2159
|
+
if (nodes.length < NODE_INDEX_MIN_SIZE) {
|
|
2160
|
+
return nodes;
|
|
2161
|
+
}
|
|
2162
|
+
const nodeVersion = this.entityManager.getEntityVersion(WorkflowNodeEntity);
|
|
2163
|
+
const transformVersion = this.entityManager.getEntityDataVersion(FlowNodeTransformData3);
|
|
2164
|
+
const activatedID = this.selectService.activatedNode?.id;
|
|
2165
|
+
if (!this.hoverNodeSpatialCache || this.hoverNodeSpatialCache.nodeVersion !== nodeVersion || this.hoverNodeSpatialCache.transformVersion !== transformVersion || this.hoverNodeSpatialCache.activatedID !== activatedID || this.hoverNodeSpatialCache.nodes !== nodes) {
|
|
2166
|
+
this.hoverNodeSpatialCache = {
|
|
2167
|
+
nodeVersion,
|
|
2168
|
+
transformVersion,
|
|
2169
|
+
activatedID,
|
|
2170
|
+
nodes,
|
|
2171
|
+
index: this.createSpatialIndex(
|
|
2172
|
+
nodes,
|
|
2173
|
+
(node) => node.getData(FlowNodeTransformData3).bounds,
|
|
2174
|
+
NODE_HIT_CELL_SIZE
|
|
2175
|
+
)
|
|
2176
|
+
};
|
|
2177
|
+
}
|
|
2178
|
+
return this.querySpatialIndex(this.hoverNodeSpatialCache.index, pos);
|
|
2179
|
+
}
|
|
2180
|
+
getSortedNodeHitCandidates(pos, sortedNodes, padding = 0) {
|
|
2181
|
+
if (sortedNodes.length < NODE_INDEX_MIN_SIZE) {
|
|
2182
|
+
return sortedNodes;
|
|
2183
|
+
}
|
|
2184
|
+
const nodeVersion = this.entityManager.getEntityVersion(WorkflowNodeEntity);
|
|
2185
|
+
const transformVersion = this.entityManager.getEntityDataVersion(FlowNodeTransformData3);
|
|
2186
|
+
if (!this.sortedNodeSpatialCache || this.sortedNodeSpatialCache.nodeVersion !== nodeVersion || this.sortedNodeSpatialCache.transformVersion !== transformVersion || this.sortedNodeSpatialCache.nodes !== sortedNodes) {
|
|
2187
|
+
this.sortedNodeSpatialCache = {
|
|
2188
|
+
nodeVersion,
|
|
2189
|
+
transformVersion,
|
|
2190
|
+
nodes: sortedNodes,
|
|
2191
|
+
index: this.createSpatialIndex(
|
|
2192
|
+
sortedNodes,
|
|
2193
|
+
(node) => node.getData(FlowNodeTransformData3).bounds,
|
|
2194
|
+
NODE_HIT_CELL_SIZE
|
|
2195
|
+
)
|
|
2196
|
+
};
|
|
2197
|
+
}
|
|
2198
|
+
return this.querySpatialIndex(this.sortedNodeSpatialCache.index, pos, padding);
|
|
2199
|
+
}
|
|
2200
|
+
getLineHitCandidates(pos, padding) {
|
|
2201
|
+
const lines = this.getAllLines();
|
|
2202
|
+
if (lines.length < LINE_INDEX_MIN_SIZE) {
|
|
2203
|
+
return lines;
|
|
2204
|
+
}
|
|
2205
|
+
const lineVersion = this.entityManager.getEntityVersion(WorkflowLineEntity);
|
|
2206
|
+
const portVersion = this.entityManager.getEntityVersion(WorkflowPortEntity);
|
|
2207
|
+
const transformVersion = this.entityManager.getEntityDataVersion(FlowNodeTransformData3);
|
|
2208
|
+
if (!this.lineSpatialCache || this.lineSpatialCache.lineVersion !== lineVersion || this.lineSpatialCache.portVersion !== portVersion || this.lineSpatialCache.transformVersion !== transformVersion) {
|
|
2209
|
+
this.lineSpatialCache = {
|
|
2210
|
+
lineVersion,
|
|
2211
|
+
portVersion,
|
|
2212
|
+
transformVersion,
|
|
2213
|
+
index: this.createSpatialIndex(lines, (line) => line.bounds, LINE_HIT_CELL_SIZE)
|
|
2214
|
+
};
|
|
2215
|
+
}
|
|
2216
|
+
return this.querySpatialIndex(this.lineSpatialCache.index, pos, padding);
|
|
2217
|
+
}
|
|
2218
|
+
createSpatialIndex(items, getBounds, cellSize) {
|
|
2219
|
+
const index = {
|
|
2220
|
+
cellSize,
|
|
2221
|
+
cells: /* @__PURE__ */ new Map(),
|
|
2222
|
+
overflowItems: [],
|
|
2223
|
+
order: /* @__PURE__ */ new Map()
|
|
2224
|
+
};
|
|
2225
|
+
items.forEach((item, itemIndex) => {
|
|
2226
|
+
index.order.set(item, itemIndex);
|
|
2227
|
+
const bounds = getBounds(item);
|
|
2228
|
+
if (!this.canIndexBounds(bounds)) {
|
|
2229
|
+
index.overflowItems.push(item);
|
|
2230
|
+
return;
|
|
2231
|
+
}
|
|
2232
|
+
const minCellX = this.getSpatialCell(bounds.x, cellSize);
|
|
2233
|
+
const maxCellX = this.getSpatialCell(bounds.right, cellSize);
|
|
2234
|
+
const minCellY = this.getSpatialCell(bounds.y, cellSize);
|
|
2235
|
+
const maxCellY = this.getSpatialCell(bounds.bottom, cellSize);
|
|
2236
|
+
const cellCount = (maxCellX - minCellX + 1) * (maxCellY - minCellY + 1);
|
|
2237
|
+
if (cellCount > MAX_SPATIAL_CELLS_PER_ITEM) {
|
|
2238
|
+
index.overflowItems.push(item);
|
|
2239
|
+
return;
|
|
2240
|
+
}
|
|
2241
|
+
for (let x = minCellX; x <= maxCellX; x++) {
|
|
2242
|
+
for (let y = minCellY; y <= maxCellY; y++) {
|
|
2243
|
+
const key = this.getSpatialCellKey(x, y);
|
|
2244
|
+
let cellItems = index.cells.get(key);
|
|
2245
|
+
if (!cellItems) {
|
|
2246
|
+
cellItems = [];
|
|
2247
|
+
index.cells.set(key, cellItems);
|
|
2248
|
+
}
|
|
2249
|
+
cellItems.push(item);
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
});
|
|
2253
|
+
return index;
|
|
2254
|
+
}
|
|
2255
|
+
querySpatialIndex(index, pos, padding = 0) {
|
|
2256
|
+
const minCellX = this.getSpatialCell(pos.x - padding, index.cellSize);
|
|
2257
|
+
const maxCellX = this.getSpatialCell(pos.x + padding, index.cellSize);
|
|
2258
|
+
const minCellY = this.getSpatialCell(pos.y - padding, index.cellSize);
|
|
2259
|
+
const maxCellY = this.getSpatialCell(pos.y + padding, index.cellSize);
|
|
2260
|
+
const candidates = [];
|
|
2261
|
+
const candidateSet = /* @__PURE__ */ new Set();
|
|
2262
|
+
const pushCandidate = (item) => {
|
|
2263
|
+
if (candidateSet.has(item)) {
|
|
2264
|
+
return;
|
|
2265
|
+
}
|
|
2266
|
+
candidateSet.add(item);
|
|
2267
|
+
candidates.push(item);
|
|
2268
|
+
};
|
|
2269
|
+
for (let x = minCellX; x <= maxCellX; x++) {
|
|
2270
|
+
for (let y = minCellY; y <= maxCellY; y++) {
|
|
2271
|
+
const cellItems = index.cells.get(this.getSpatialCellKey(x, y));
|
|
2272
|
+
if (cellItems) {
|
|
2273
|
+
cellItems.forEach(pushCandidate);
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
index.overflowItems.forEach(pushCandidate);
|
|
2278
|
+
return candidates.sort((a, b) => (index.order.get(a) ?? 0) - (index.order.get(b) ?? 0));
|
|
2279
|
+
}
|
|
2280
|
+
getSpatialCell(value, cellSize) {
|
|
2281
|
+
return Math.floor(value / cellSize);
|
|
2282
|
+
}
|
|
2283
|
+
getSpatialCellKey(x, y) {
|
|
2284
|
+
return `${x}:${y}`;
|
|
2285
|
+
}
|
|
2286
|
+
canIndexBounds(bounds) {
|
|
2287
|
+
return Number.isFinite(bounds.x) && Number.isFinite(bounds.y) && Number.isFinite(bounds.width) && Number.isFinite(bounds.height) && bounds.width > 0 && bounds.height > 0;
|
|
2288
|
+
}
|
|
2289
|
+
isPointNearNodePorts(pos, node) {
|
|
2290
|
+
const { bounds } = node.getData(FlowNodeTransformData3);
|
|
2291
|
+
return this.isPointInBounds(pos, bounds, PORT_NODE_BOUNDS_PADDING);
|
|
2292
|
+
}
|
|
2293
|
+
hasPortOutsideNodeBounds(node) {
|
|
2294
|
+
const { bounds } = node.getData(FlowNodeTransformData3);
|
|
2295
|
+
return node.ports.allPorts.some((port) => {
|
|
2296
|
+
if (port.targetElement) {
|
|
2297
|
+
return true;
|
|
2298
|
+
}
|
|
2299
|
+
return !this.isPointInBounds(port.point, bounds, PORT_NODE_BOUNDS_PADDING);
|
|
2300
|
+
});
|
|
2301
|
+
}
|
|
2302
|
+
getOutsidePortNodes(sortedNodes) {
|
|
2303
|
+
const nodeVersion = this.entityManager.getEntityVersion(WorkflowNodeEntity);
|
|
2304
|
+
const portVersion = this.entityManager.getEntityVersion(WorkflowPortEntity);
|
|
2305
|
+
const transformVersion = this.entityManager.getEntityDataVersion(FlowNodeTransformData3);
|
|
2306
|
+
if (this.outsidePortNodesCache && this.outsidePortNodesCache.nodeVersion === nodeVersion && this.outsidePortNodesCache.portVersion === portVersion && this.outsidePortNodesCache.transformVersion === transformVersion && this.outsidePortNodesCache.sortedNodes === sortedNodes) {
|
|
2307
|
+
return this.outsidePortNodesCache.outsideNodes;
|
|
2308
|
+
}
|
|
2309
|
+
const outsideNodes = sortedNodes.filter((node) => this.hasPortOutsideNodeBounds(node));
|
|
2310
|
+
this.outsidePortNodesCache = {
|
|
2311
|
+
nodeVersion,
|
|
2312
|
+
portVersion,
|
|
2313
|
+
transformVersion,
|
|
2314
|
+
sortedNodes,
|
|
2315
|
+
outsideNodes
|
|
2316
|
+
};
|
|
2317
|
+
return outsideNodes;
|
|
2318
|
+
}
|
|
2319
|
+
getHoverNodes() {
|
|
2320
|
+
const nodeVersion = this.entityManager.getEntityVersion(WorkflowNodeEntity);
|
|
2321
|
+
const activatedID = this.selectService.activatedNode?.id;
|
|
2322
|
+
if (this.hoverNodesCache && this.hoverNodesCacheVersion === nodeVersion && this.hoverNodesCacheActivatedID === activatedID) {
|
|
2323
|
+
return this.hoverNodesCache;
|
|
2324
|
+
}
|
|
2325
|
+
const nodes = this.document.getAllNodes().filter(
|
|
2326
|
+
(node) => node.id !== "root" && node.flowNodeType !== FlowNodeBaseType2.ROOT && node.flowNodeType !== FlowNodeBaseType2.GROUP
|
|
2327
|
+
).reverse();
|
|
2328
|
+
if (activatedID) {
|
|
2329
|
+
const activatedIndex = nodes.findIndex((node) => node.id === activatedID);
|
|
2330
|
+
if (activatedIndex > 0) {
|
|
2331
|
+
const [activatedNode] = nodes.splice(activatedIndex, 1);
|
|
2332
|
+
nodes.unshift(activatedNode);
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
this.hoverNodesCache = nodes;
|
|
2336
|
+
this.hoverNodesCacheVersion = nodeVersion;
|
|
2337
|
+
this.hoverNodesCacheActivatedID = activatedID;
|
|
2338
|
+
this.hoverNodeSpatialCache = void 0;
|
|
2339
|
+
return this.hoverNodesCache;
|
|
2340
|
+
}
|
|
2341
|
+
isPointInBounds(pos, bounds, padding = 0) {
|
|
2342
|
+
if (bounds.width + padding * 2 <= 0 || bounds.height + padding * 2 <= 0) {
|
|
2343
|
+
return false;
|
|
2344
|
+
}
|
|
2345
|
+
return pos.x >= bounds.x - padding && pos.x <= bounds.right + padding && pos.y >= bounds.y - padding && pos.y <= bounds.bottom + padding;
|
|
1937
2346
|
}
|
|
1938
2347
|
getNodeIndex(node) {
|
|
1939
2348
|
const nodeRenderData = node.getData(FlowNodeRenderData2);
|
|
@@ -1963,7 +2372,7 @@ import { Emitter as Emitter5 } from "@flowgram.ai/utils";
|
|
|
1963
2372
|
import { NodeEngineContext } from "@flowgram.ai/form-core";
|
|
1964
2373
|
import {
|
|
1965
2374
|
FlowDocument,
|
|
1966
|
-
FlowNodeBaseType as
|
|
2375
|
+
FlowNodeBaseType as FlowNodeBaseType3,
|
|
1967
2376
|
FlowNodeTransformData as FlowNodeTransformData5
|
|
1968
2377
|
} from "@flowgram.ai/document";
|
|
1969
2378
|
import {
|
|
@@ -2277,7 +2686,7 @@ var WorkflowDocument = class extends FlowDocument {
|
|
|
2277
2686
|
toJSON: () => this.toNodeJSON(node)
|
|
2278
2687
|
});
|
|
2279
2688
|
node.onDispose(() => {
|
|
2280
|
-
if (!node.parent || node.parent.flowNodeType ===
|
|
2689
|
+
if (!node.parent || node.parent.flowNodeType === FlowNodeBaseType3.ROOT) {
|
|
2281
2690
|
return;
|
|
2282
2691
|
}
|
|
2283
2692
|
const parentTransform = node.parent.getData(FlowNodeTransformData5);
|
|
@@ -2448,13 +2857,13 @@ var WorkflowDocument = class extends FlowDocument {
|
|
|
2448
2857
|
);
|
|
2449
2858
|
}
|
|
2450
2859
|
getAllNodes() {
|
|
2451
|
-
return this.entityManager.getEntities(WorkflowNodeEntity).filter((n) => n.id !==
|
|
2860
|
+
return this.entityManager.getEntities(WorkflowNodeEntity).filter((n) => n.id !== FlowNodeBaseType3.ROOT);
|
|
2452
2861
|
}
|
|
2453
2862
|
getAllEdges() {
|
|
2454
2863
|
return this.entityManager.getEntities(WorkflowLineEntity);
|
|
2455
2864
|
}
|
|
2456
2865
|
getAllPorts() {
|
|
2457
|
-
return this.entityManager.getEntities(WorkflowPortEntity).filter((p) => p.node.id !==
|
|
2866
|
+
return this.entityManager.getEntities(WorkflowPortEntity).filter((p) => p.node.id !== FlowNodeBaseType3.ROOT);
|
|
2458
2867
|
}
|
|
2459
2868
|
/**
|
|
2460
2869
|
* 获取画布中的非游离节点
|
|
@@ -2666,7 +3075,7 @@ var WorkflowDocument = class extends FlowDocument {
|
|
|
2666
3075
|
return subCanvas;
|
|
2667
3076
|
}
|
|
2668
3077
|
getNodeChildren(node) {
|
|
2669
|
-
if (!node || node.flowNodeType ===
|
|
3078
|
+
if (!node || node.flowNodeType === FlowNodeBaseType3.GROUP) return [];
|
|
2670
3079
|
const subCanvas = this.getNodeSubCanvas(node);
|
|
2671
3080
|
const realChildren = subCanvas ? subCanvas.canvasNode.blocks : node.blocks;
|
|
2672
3081
|
const childrenWithoutSubCanvas = realChildren.filter((child) => {
|
|
@@ -2674,7 +3083,7 @@ var WorkflowDocument = class extends FlowDocument {
|
|
|
2674
3083
|
return !childMeta.subCanvas?.(node)?.isCanvas;
|
|
2675
3084
|
}).filter(Boolean);
|
|
2676
3085
|
const children = childrenWithoutSubCanvas.map((child) => {
|
|
2677
|
-
if (child.flowNodeType ===
|
|
3086
|
+
if (child.flowNodeType === FlowNodeBaseType3.GROUP) {
|
|
2678
3087
|
return [child, ...child.blocks];
|
|
2679
3088
|
}
|
|
2680
3089
|
return child;
|
|
@@ -2993,7 +3402,7 @@ var WorkflowDragService = class {
|
|
|
2993
3402
|
if (!mousePos) {
|
|
2994
3403
|
return { x: 0, y: 0 };
|
|
2995
3404
|
}
|
|
2996
|
-
if (!subNodeType || !containerNode || containerNode.flowNodeType ===
|
|
3405
|
+
if (!subNodeType || !containerNode || containerNode.flowNodeType === FlowNodeBaseType4.ROOT) {
|
|
2997
3406
|
return mousePos;
|
|
2998
3407
|
}
|
|
2999
3408
|
const isParentEmpty = !containerNode.children || containerNode.children.length === 0;
|
|
@@ -3206,7 +3615,7 @@ var WorkflowDragService = class {
|
|
|
3206
3615
|
return;
|
|
3207
3616
|
}
|
|
3208
3617
|
const sourceContainer = nodes[0]?.parent;
|
|
3209
|
-
if (!sourceContainer || sourceContainer.flowNodeType ===
|
|
3618
|
+
if (!sourceContainer || sourceContainer.flowNodeType === FlowNodeBaseType4.ROOT) {
|
|
3210
3619
|
return;
|
|
3211
3620
|
}
|
|
3212
3621
|
const valid = nodes.every((node) => node?.parent === sourceContainer);
|
|
@@ -3351,15 +3760,15 @@ var WorkflowDragService = class {
|
|
|
3351
3760
|
}
|
|
3352
3761
|
updateDrawingLine(isDrawingTo, line, dragPos, originLine) {
|
|
3353
3762
|
let hasError = false;
|
|
3354
|
-
const mouseNode = this.linesManager.getNodeFromMousePos(dragPos);
|
|
3355
3763
|
let toNode;
|
|
3356
3764
|
let toPort;
|
|
3357
3765
|
let fromPort;
|
|
3358
3766
|
let fromNode;
|
|
3359
3767
|
if (isDrawingTo) {
|
|
3768
|
+
const mouseHitInfo = this.linesManager.getNodeAndPortFromMousePos(dragPos, "input");
|
|
3360
3769
|
fromPort = line.fromPort;
|
|
3361
|
-
toNode =
|
|
3362
|
-
toPort =
|
|
3770
|
+
toNode = mouseHitInfo.node;
|
|
3771
|
+
toPort = mouseHitInfo.port;
|
|
3363
3772
|
if (toNode && this.canBuildContainerLine(toNode, dragPos)) {
|
|
3364
3773
|
toPort = this.getNearestPort(toNode, dragPos, "input");
|
|
3365
3774
|
hasError = this.checkDraggingPort(isDrawingTo, line, toNode, toPort, originLine).hasError;
|
|
@@ -3386,9 +3795,10 @@ var WorkflowDragService = class {
|
|
|
3386
3795
|
};
|
|
3387
3796
|
}
|
|
3388
3797
|
} else {
|
|
3798
|
+
const mouseHitInfo = this.linesManager.getNodeAndPortFromMousePos(dragPos, "output");
|
|
3389
3799
|
toPort = line.toPort;
|
|
3390
|
-
fromNode =
|
|
3391
|
-
fromPort =
|
|
3800
|
+
fromNode = mouseHitInfo.node;
|
|
3801
|
+
fromPort = mouseHitInfo.port;
|
|
3392
3802
|
if (fromNode && this.canBuildContainerLine(fromNode, dragPos)) {
|
|
3393
3803
|
fromPort = this.getNearestPort(fromNode, dragPos, "output");
|
|
3394
3804
|
hasError = this.checkDraggingPort(
|