@elicdavis/node-flow 0.1.16 → 0.1.17
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/index.d.mts +97 -4
- package/dist/index.d.ts +97 -4
- package/dist/index.js +643 -69
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +637 -68
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/graph.ts +234 -41
- package/src/index.ts +16 -0
- package/src/input.ts +22 -14
- package/src/markdown/entry.ts +6 -2
- package/src/minimap.ts +178 -0
- package/src/node.ts +80 -1
- package/src/nodes/factory.ts +9 -5
- package/src/nodes/publisher.ts +39 -4
- package/src/nodes/subsystem.ts +211 -1
- package/src/notes/subsystem.ts +3 -0
- package/src/port.ts +17 -4
- package/src/render_scheduler.ts +49 -0
- package/src/theme.ts +8 -0
- package/src/types/text.ts +2 -0
- package/src/widgets/image.ts +2 -0
- package/test/minimap.test.ts +103 -0
- package/test/node_menu_filter.test.ts +119 -0
- package/test/render_scheduler.test.ts +119 -0
package/dist/index.mjs
CHANGED
|
@@ -60,6 +60,14 @@ var Theme = {
|
|
|
60
60
|
FontColor: "#afb9bb",
|
|
61
61
|
DisabledFontColor: "#4a585c"
|
|
62
62
|
},
|
|
63
|
+
Minimap: {
|
|
64
|
+
BackgroundColor: "rgba(7, 33, 42, 0.85)",
|
|
65
|
+
BorderColor: "#1c1c1c",
|
|
66
|
+
BorderRadius: 4,
|
|
67
|
+
Padding: 6,
|
|
68
|
+
NodeColor: "#6b7f85",
|
|
69
|
+
ViewportColor: "rgba(175, 185, 187, 0.25)"
|
|
70
|
+
},
|
|
63
71
|
Note: {
|
|
64
72
|
FontColor: "#afb9bb",
|
|
65
73
|
FontSize: 16,
|
|
@@ -601,6 +609,43 @@ var ContextMenu = class _ContextMenu {
|
|
|
601
609
|
}
|
|
602
610
|
};
|
|
603
611
|
|
|
612
|
+
// src/render_scheduler.ts
|
|
613
|
+
var subscribers = /* @__PURE__ */ new Set();
|
|
614
|
+
var frameQueued = false;
|
|
615
|
+
var continuous = 0;
|
|
616
|
+
var canSchedule = () => typeof requestAnimationFrame === "function";
|
|
617
|
+
function onRenderRequested(redraw) {
|
|
618
|
+
subscribers.add(redraw);
|
|
619
|
+
return () => {
|
|
620
|
+
subscribers.delete(redraw);
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
function requestRender() {
|
|
624
|
+
if (frameQueued || !canSchedule()) {
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
frameQueued = true;
|
|
628
|
+
requestAnimationFrame(() => {
|
|
629
|
+
frameQueued = false;
|
|
630
|
+
subscribers.forEach((redraw) => redraw());
|
|
631
|
+
if (continuous > 0) {
|
|
632
|
+
requestRender();
|
|
633
|
+
}
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
function renderContinuously() {
|
|
637
|
+
continuous++;
|
|
638
|
+
requestRender();
|
|
639
|
+
let released = false;
|
|
640
|
+
return () => {
|
|
641
|
+
if (released) {
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
released = true;
|
|
645
|
+
continuous--;
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
|
|
604
649
|
// src/input.ts
|
|
605
650
|
var LONG_PRESS_MS = 500;
|
|
606
651
|
var LONG_PRESS_SLOP = 12;
|
|
@@ -634,15 +679,19 @@ var MouseObserver = class {
|
|
|
634
679
|
this.#lastTouch = Zero();
|
|
635
680
|
this.#lastMousePosition = Zero();
|
|
636
681
|
ele.style.touchAction = "none";
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
ele.addEventListener("
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
682
|
+
const redraws = (handler) => (event) => {
|
|
683
|
+
handler(event);
|
|
684
|
+
requestRender();
|
|
685
|
+
};
|
|
686
|
+
ele.addEventListener("mousedown", redraws(this.#down.bind(this)), false);
|
|
687
|
+
ele.addEventListener("touchstart", redraws(this.#touchStart.bind(this)), { passive: false });
|
|
688
|
+
document.addEventListener("mouseup", redraws(this.#up.bind(this)), false);
|
|
689
|
+
document.addEventListener("touchend", redraws(this.#touchEnd.bind(this)), false);
|
|
690
|
+
document.addEventListener("touchcancel", redraws(this.#touchEnd.bind(this)), false);
|
|
691
|
+
ele.addEventListener("mousemove", redraws(this.#move.bind(this)), false);
|
|
692
|
+
ele.addEventListener("touchmove", redraws(this.#touchMove.bind(this)), { passive: false });
|
|
693
|
+
ele.addEventListener("wheel", redraws(this.#wheel.bind(this)), { passive: false });
|
|
694
|
+
ele.addEventListener("drop", redraws((ev) => {
|
|
646
695
|
ev.preventDefault();
|
|
647
696
|
if (ev.dataTransfer?.items) {
|
|
648
697
|
[...ev.dataTransfer.items].forEach((item, i) => {
|
|
@@ -654,18 +703,18 @@ var MouseObserver = class {
|
|
|
654
703
|
}
|
|
655
704
|
});
|
|
656
705
|
}
|
|
657
|
-
});
|
|
658
|
-
ele.addEventListener("dragover", (ev) => {
|
|
706
|
+
}));
|
|
707
|
+
ele.addEventListener("dragover", redraws((ev) => {
|
|
659
708
|
ev.preventDefault();
|
|
660
709
|
this.#moveCallback(this.#mousePos(ev));
|
|
661
|
-
});
|
|
662
|
-
ele.addEventListener("contextmenu", (evt) => {
|
|
710
|
+
}));
|
|
711
|
+
ele.addEventListener("contextmenu", redraws((evt) => {
|
|
663
712
|
evt.preventDefault();
|
|
664
713
|
if (Date.now() - this.#lastTouchAt < SUPPRESS_MOUSE_MS) {
|
|
665
714
|
return;
|
|
666
715
|
}
|
|
667
716
|
this.#contextMenu(this.#mousePos(evt));
|
|
668
|
-
}, false);
|
|
717
|
+
}), false);
|
|
669
718
|
}
|
|
670
719
|
#mousePos(event) {
|
|
671
720
|
const rect = this.#ele.getBoundingClientRect();
|
|
@@ -762,6 +811,7 @@ var MouseObserver = class {
|
|
|
762
811
|
this.#clicked = false;
|
|
763
812
|
this.#clickStop();
|
|
764
813
|
this.#contextMenu({ x, y });
|
|
814
|
+
requestRender();
|
|
765
815
|
}, LONG_PRESS_MS);
|
|
766
816
|
this.#clicked = true;
|
|
767
817
|
this.#moveCallback(pos);
|
|
@@ -1198,6 +1248,7 @@ var Text = class _Text {
|
|
|
1198
1248
|
if (!document.fonts.check(`16px "${this.#style.getFont()}"`)) {
|
|
1199
1249
|
document.fonts.addEventListener("loadingdone", () => {
|
|
1200
1250
|
this.#measured = false;
|
|
1251
|
+
requestRender();
|
|
1201
1252
|
});
|
|
1202
1253
|
}
|
|
1203
1254
|
}
|
|
@@ -1409,12 +1460,22 @@ function portsCompatible(a, b) {
|
|
|
1409
1460
|
if (!a || !b) {
|
|
1410
1461
|
return false;
|
|
1411
1462
|
}
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1463
|
+
return typeSetsCompatible(a.acceptedTypes(), b.acceptedTypes());
|
|
1464
|
+
}
|
|
1465
|
+
function typeSetsCompatible(a, b) {
|
|
1466
|
+
if (a.length === 0 || b.length === 0) {
|
|
1415
1467
|
return true;
|
|
1416
1468
|
}
|
|
1417
|
-
return
|
|
1469
|
+
return a.some((type) => b.includes(type));
|
|
1470
|
+
}
|
|
1471
|
+
function portConfigTypes(config) {
|
|
1472
|
+
if (config.anyType === true) {
|
|
1473
|
+
return [];
|
|
1474
|
+
}
|
|
1475
|
+
if (config.acceptedTypes !== void 0 && config.acceptedTypes.length > 0) {
|
|
1476
|
+
return config.acceptedTypes;
|
|
1477
|
+
}
|
|
1478
|
+
return [config.type === void 0 ? "" : config.type];
|
|
1418
1479
|
}
|
|
1419
1480
|
function fallbackColor(type, s) {
|
|
1420
1481
|
let value = 0;
|
|
@@ -1529,6 +1590,7 @@ var Port = class {
|
|
|
1529
1590
|
this.#filledStyle.fillColor = fallbackColor(this.#dataType, 1);
|
|
1530
1591
|
}
|
|
1531
1592
|
this.#dataTypePopupElement = this.#buildTooltip();
|
|
1593
|
+
requestRender();
|
|
1532
1594
|
}
|
|
1533
1595
|
setDataType(type) {
|
|
1534
1596
|
if (this.#dataType === type) {
|
|
@@ -2607,6 +2669,7 @@ var ImageWidget = class {
|
|
|
2607
2669
|
img.src = url;
|
|
2608
2670
|
img.onload = () => {
|
|
2609
2671
|
this.#image = img;
|
|
2672
|
+
requestRender();
|
|
2610
2673
|
};
|
|
2611
2674
|
img.onerror = (event) => {
|
|
2612
2675
|
console.log("error loading image:", url, event);
|
|
@@ -3187,6 +3250,13 @@ function TimeExecution(name, callback) {
|
|
|
3187
3250
|
}
|
|
3188
3251
|
|
|
3189
3252
|
// src/nodes/publisher.ts
|
|
3253
|
+
function offersMatchingPort(config, filter) {
|
|
3254
|
+
const ports = filter.needs === "INPUT" /* Input */ ? config.inputs : config.outputs;
|
|
3255
|
+
if (ports === void 0) {
|
|
3256
|
+
return false;
|
|
3257
|
+
}
|
|
3258
|
+
return ports.some((port) => typeSetsCompatible(portConfigTypes(port), filter.types));
|
|
3259
|
+
}
|
|
3190
3260
|
var Publisher = class {
|
|
3191
3261
|
#name;
|
|
3192
3262
|
#description;
|
|
@@ -3212,19 +3282,23 @@ var Publisher = class {
|
|
|
3212
3282
|
unregister(nodeType) {
|
|
3213
3283
|
return this.#registeredNodes.delete(nodeType);
|
|
3214
3284
|
}
|
|
3215
|
-
#recurseBuildMenu(graph, name, subMenu, position) {
|
|
3285
|
+
#recurseBuildMenu(graph, name, subMenu, position, filter) {
|
|
3216
3286
|
const items = [];
|
|
3217
3287
|
const subMenus = /* @__PURE__ */ new Map();
|
|
3218
3288
|
for (let [key, nodeConfig] of subMenu) {
|
|
3219
3289
|
const slashIndex = key.indexOf("/");
|
|
3220
3290
|
const bracketIndex = key.indexOf("[");
|
|
3221
3291
|
if (slashIndex === -1 || bracketIndex !== -1 && bracketIndex < slashIndex) {
|
|
3292
|
+
if (filter !== void 0 && !offersMatchingPort(nodeConfig, filter)) {
|
|
3293
|
+
continue;
|
|
3294
|
+
}
|
|
3222
3295
|
items.push({
|
|
3223
3296
|
name: key,
|
|
3224
3297
|
callback: () => {
|
|
3225
3298
|
const node = new FlowNode(nodeConfig);
|
|
3226
3299
|
node.setPosition(position);
|
|
3227
3300
|
graph.addNode(node);
|
|
3301
|
+
filter?.onCreated?.(node);
|
|
3228
3302
|
}
|
|
3229
3303
|
});
|
|
3230
3304
|
} else {
|
|
@@ -3239,7 +3313,11 @@ var Publisher = class {
|
|
|
3239
3313
|
}
|
|
3240
3314
|
const menus = [];
|
|
3241
3315
|
for (let [key, nodes] of subMenus) {
|
|
3242
|
-
|
|
3316
|
+
const built = this.#recurseBuildMenu(graph, key, nodes, position, filter);
|
|
3317
|
+
if (filter !== void 0 && built.items?.length === 0 && built.subMenus?.length === 0) {
|
|
3318
|
+
continue;
|
|
3319
|
+
}
|
|
3320
|
+
menus.push(built);
|
|
3243
3321
|
}
|
|
3244
3322
|
return {
|
|
3245
3323
|
name,
|
|
@@ -3247,8 +3325,8 @@ var Publisher = class {
|
|
|
3247
3325
|
subMenus: menus
|
|
3248
3326
|
};
|
|
3249
3327
|
}
|
|
3250
|
-
contextMenu(graph, position) {
|
|
3251
|
-
return this.#recurseBuildMenu(graph, this.#name, this.#registeredNodes, position);
|
|
3328
|
+
contextMenu(graph, position, filter) {
|
|
3329
|
+
return this.#recurseBuildMenu(graph, this.#name, this.#registeredNodes, position, filter);
|
|
3252
3330
|
}
|
|
3253
3331
|
create(nodeType) {
|
|
3254
3332
|
const config = this.#registeredNodes.get(nodeType);
|
|
@@ -3303,18 +3381,22 @@ var NodeFactory = class {
|
|
|
3303
3381
|
}
|
|
3304
3382
|
return node;
|
|
3305
3383
|
}
|
|
3306
|
-
newNodeSubmenus(graph, position) {
|
|
3384
|
+
newNodeSubmenus(graph, position, filter) {
|
|
3307
3385
|
const menus = [];
|
|
3308
3386
|
for (let [_, publisher] of this.#registeredPublishers) {
|
|
3309
|
-
|
|
3387
|
+
const built = publisher.contextMenu(graph, position, filter);
|
|
3388
|
+
if (filter !== void 0 && built.items?.length === 0 && built.subMenus?.length === 0) {
|
|
3389
|
+
continue;
|
|
3390
|
+
}
|
|
3391
|
+
menus.push(built);
|
|
3310
3392
|
}
|
|
3311
3393
|
return menus;
|
|
3312
3394
|
}
|
|
3313
|
-
openMenu(graph, position) {
|
|
3395
|
+
openMenu(graph, position, filter) {
|
|
3314
3396
|
return {
|
|
3315
3397
|
name: "New Node",
|
|
3316
3398
|
group: nodeFlowGroup,
|
|
3317
|
-
subMenus: this.newNodeSubmenus(graph, position)
|
|
3399
|
+
subMenus: this.newNodeSubmenus(graph, position, filter)
|
|
3318
3400
|
};
|
|
3319
3401
|
}
|
|
3320
3402
|
};
|
|
@@ -3453,6 +3535,9 @@ var NodeSubsystem2 = class {
|
|
|
3453
3535
|
CopyVector2(this.#boxSelectEnd_graphSpace, this.#boxSelectStart_graphSpace);
|
|
3454
3536
|
this.#boxSelect = true;
|
|
3455
3537
|
}
|
|
3538
|
+
if (!hoveringSomething && !ctrlKey) {
|
|
3539
|
+
this.unselectAllNodes();
|
|
3540
|
+
}
|
|
3456
3541
|
return hoveringSomething || ctrlKey;
|
|
3457
3542
|
}
|
|
3458
3543
|
if (this.#portHovering.InputPort) {
|
|
@@ -3512,6 +3597,102 @@ var NodeSubsystem2 = class {
|
|
|
3512
3597
|
}
|
|
3513
3598
|
}
|
|
3514
3599
|
}
|
|
3600
|
+
connectionsWithin(nodes) {
|
|
3601
|
+
const within = [];
|
|
3602
|
+
for (const connection of this.#connections) {
|
|
3603
|
+
const outNode = connection.outNode();
|
|
3604
|
+
const inNode = connection.inNode();
|
|
3605
|
+
if (outNode === null || inNode === null) {
|
|
3606
|
+
continue;
|
|
3607
|
+
}
|
|
3608
|
+
const from = nodes.indexOf(outNode);
|
|
3609
|
+
const to = nodes.indexOf(inNode);
|
|
3610
|
+
if (from === -1 || to === -1) {
|
|
3611
|
+
continue;
|
|
3612
|
+
}
|
|
3613
|
+
const outPort = connection.outPort();
|
|
3614
|
+
const inPort = connection.inPort();
|
|
3615
|
+
if (outPort === null || inPort === null) {
|
|
3616
|
+
continue;
|
|
3617
|
+
}
|
|
3618
|
+
within.push({
|
|
3619
|
+
fromNode: from,
|
|
3620
|
+
fromPort: this.#outputPortIndex(outNode, outPort),
|
|
3621
|
+
toNode: to,
|
|
3622
|
+
toPort: this.#inputPortIndex(inNode, inPort)
|
|
3623
|
+
});
|
|
3624
|
+
}
|
|
3625
|
+
return within;
|
|
3626
|
+
}
|
|
3627
|
+
#onConnectionReleased = null;
|
|
3628
|
+
setConnectionReleasedHandler(handler) {
|
|
3629
|
+
this.#onConnectionReleased = handler;
|
|
3630
|
+
}
|
|
3631
|
+
#describeDanglingConnection(conn) {
|
|
3632
|
+
const outNode = conn.outNode();
|
|
3633
|
+
const inNode = conn.inNode();
|
|
3634
|
+
if (outNode !== null && inNode === null) {
|
|
3635
|
+
const from = conn.outPort();
|
|
3636
|
+
if (from === null) {
|
|
3637
|
+
return null;
|
|
3638
|
+
}
|
|
3639
|
+
const fromIndex = this.#outputPortIndex(outNode, from);
|
|
3640
|
+
return {
|
|
3641
|
+
needs: "INPUT" /* Input */,
|
|
3642
|
+
types: from.acceptedTypes(),
|
|
3643
|
+
connectTo: (node) => {
|
|
3644
|
+
const to = this.#firstCompatiblePort(node, "INPUT" /* Input */, from);
|
|
3645
|
+
if (to !== -1 && fromIndex !== -1) {
|
|
3646
|
+
this.connectNodes(outNode, fromIndex, node, to);
|
|
3647
|
+
}
|
|
3648
|
+
}
|
|
3649
|
+
};
|
|
3650
|
+
}
|
|
3651
|
+
if (inNode !== null && outNode === null) {
|
|
3652
|
+
const to = conn.inPort();
|
|
3653
|
+
if (to === null) {
|
|
3654
|
+
return null;
|
|
3655
|
+
}
|
|
3656
|
+
const toIndex = this.#inputPortIndex(inNode, to);
|
|
3657
|
+
return {
|
|
3658
|
+
needs: "OUTPUT" /* Output */,
|
|
3659
|
+
types: to.acceptedTypes(),
|
|
3660
|
+
connectTo: (node) => {
|
|
3661
|
+
const from = this.#firstCompatiblePort(node, "OUTPUT" /* Output */, to);
|
|
3662
|
+
if (from !== -1 && toIndex !== -1) {
|
|
3663
|
+
this.connectNodes(node, from, inNode, toIndex);
|
|
3664
|
+
}
|
|
3665
|
+
}
|
|
3666
|
+
};
|
|
3667
|
+
}
|
|
3668
|
+
return null;
|
|
3669
|
+
}
|
|
3670
|
+
#outputPortIndex(node, port) {
|
|
3671
|
+
for (let i = 0; i < node.outputs(); i++) {
|
|
3672
|
+
if (node.outputPort(i) === port) {
|
|
3673
|
+
return i;
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3676
|
+
return -1;
|
|
3677
|
+
}
|
|
3678
|
+
#inputPortIndex(node, port) {
|
|
3679
|
+
for (let i = 0; i < node.inputs(); i++) {
|
|
3680
|
+
if (node.inputPort(i) === port) {
|
|
3681
|
+
return i;
|
|
3682
|
+
}
|
|
3683
|
+
}
|
|
3684
|
+
return -1;
|
|
3685
|
+
}
|
|
3686
|
+
#firstCompatiblePort(node, side, against) {
|
|
3687
|
+
const count = side === "INPUT" /* Input */ ? node.inputs() : node.outputs();
|
|
3688
|
+
for (let i = 0; i < count; i++) {
|
|
3689
|
+
const port = side === "INPUT" /* Input */ ? node.inputPort(i) : node.outputPort(i);
|
|
3690
|
+
if (portsCompatible(port, against)) {
|
|
3691
|
+
return i;
|
|
3692
|
+
}
|
|
3693
|
+
}
|
|
3694
|
+
return -1;
|
|
3695
|
+
}
|
|
3515
3696
|
clickEnd() {
|
|
3516
3697
|
for (let i = 0; i < this.#nodesGrabbed.Count(); i++) {
|
|
3517
3698
|
const node = this.#nodes[this.#nodesGrabbed.At(i)];
|
|
@@ -3533,7 +3714,11 @@ var NodeSubsystem2 = class {
|
|
|
3533
3714
|
return;
|
|
3534
3715
|
}
|
|
3535
3716
|
if (this.#portHovering === null) {
|
|
3717
|
+
const dangling = this.#describeDanglingConnection(this.#connectionSelected);
|
|
3536
3718
|
this.#clearCurrentlySelectedConnection();
|
|
3719
|
+
if (dangling !== null) {
|
|
3720
|
+
this.#onConnectionReleased?.(dangling);
|
|
3721
|
+
}
|
|
3537
3722
|
return;
|
|
3538
3723
|
}
|
|
3539
3724
|
const port = this.#portHovering.Port;
|
|
@@ -3600,6 +3785,7 @@ var NodeSubsystem2 = class {
|
|
|
3600
3785
|
this.#idleConnectionRenderer
|
|
3601
3786
|
);
|
|
3602
3787
|
this.#connections.push(connection);
|
|
3788
|
+
requestRender();
|
|
3603
3789
|
return connection;
|
|
3604
3790
|
}
|
|
3605
3791
|
getNodes() {
|
|
@@ -3660,6 +3846,7 @@ var NodeSubsystem2 = class {
|
|
|
3660
3846
|
}
|
|
3661
3847
|
addNode(node) {
|
|
3662
3848
|
this.#nodes.push(node);
|
|
3849
|
+
requestRender();
|
|
3663
3850
|
for (let i = 0; i < this.#registeredNodeAddedCallbacks.length; i++) {
|
|
3664
3851
|
const callback = this.#registeredNodeAddedCallbacks[i];
|
|
3665
3852
|
if (!callback) {
|
|
@@ -3706,6 +3893,7 @@ var NodeSubsystem2 = class {
|
|
|
3706
3893
|
this.#removeNodeConnections(nodeIndex);
|
|
3707
3894
|
const node = this.#nodes[nodeIndex];
|
|
3708
3895
|
this.#nodes.splice(nodeIndex, 1);
|
|
3896
|
+
requestRender();
|
|
3709
3897
|
for (let i = 0; i < this.#nodeRemovedCallbacks.length; i++) {
|
|
3710
3898
|
this.#nodeRemovedCallbacks[i](node);
|
|
3711
3899
|
}
|
|
@@ -3715,6 +3903,7 @@ var NodeSubsystem2 = class {
|
|
|
3715
3903
|
this.#connections[index].clearPorts();
|
|
3716
3904
|
}
|
|
3717
3905
|
this.#connections.splice(index, 1);
|
|
3906
|
+
requestRender();
|
|
3718
3907
|
}
|
|
3719
3908
|
#removeConnection(connection, clearPorts) {
|
|
3720
3909
|
const index = this.#connections.indexOf(connection);
|
|
@@ -3760,7 +3949,8 @@ var NodeSubsystem2 = class {
|
|
|
3760
3949
|
this.#nodeFactory.openMenu(this, position)
|
|
3761
3950
|
]
|
|
3762
3951
|
};
|
|
3763
|
-
|
|
3952
|
+
const selectedCount = this.#nodesSelected().length;
|
|
3953
|
+
if (selectedCount > 0) {
|
|
3764
3954
|
organizeNodesSubMenu.items?.push({
|
|
3765
3955
|
name: "Selected Nodes",
|
|
3766
3956
|
group: nodeFlowGroup,
|
|
@@ -3768,6 +3958,13 @@ var NodeSubsystem2 = class {
|
|
|
3768
3958
|
this.#organizeSelected(ctx);
|
|
3769
3959
|
}
|
|
3770
3960
|
});
|
|
3961
|
+
config.items?.push({
|
|
3962
|
+
name: selectedCount === 1 ? "Delete Selected Node" : `Delete ${selectedCount} Selected Nodes`,
|
|
3963
|
+
group: nodeFlowGroup,
|
|
3964
|
+
callback: () => {
|
|
3965
|
+
this.removeSelectedNodes();
|
|
3966
|
+
}
|
|
3967
|
+
});
|
|
3771
3968
|
}
|
|
3772
3969
|
if (this.#nodeHovering > -1) {
|
|
3773
3970
|
const nodeToReview = this.#nodeHovering;
|
|
@@ -3841,6 +4038,29 @@ var NodeSubsystem2 = class {
|
|
|
3841
4038
|
this.#selectNode(inputs[i], false);
|
|
3842
4039
|
}
|
|
3843
4040
|
}
|
|
4041
|
+
/** Drops the selection entirely. */
|
|
4042
|
+
unselectAllNodes() {
|
|
4043
|
+
let changed = false;
|
|
4044
|
+
for (let i = 0; i < this.#nodes.length; i++) {
|
|
4045
|
+
if (this.#nodes[i].selected()) {
|
|
4046
|
+
this.#nodes[i].unselect();
|
|
4047
|
+
changed = true;
|
|
4048
|
+
}
|
|
4049
|
+
}
|
|
4050
|
+
if (changed) {
|
|
4051
|
+
requestRender();
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4054
|
+
/**
|
|
4055
|
+
* Removes every selected node, and the connections that touched them.
|
|
4056
|
+
*/
|
|
4057
|
+
removeSelectedNodes() {
|
|
4058
|
+
const removed = this.getSelectedNodes();
|
|
4059
|
+
for (const node of removed) {
|
|
4060
|
+
this.removeNode(node);
|
|
4061
|
+
}
|
|
4062
|
+
return removed;
|
|
4063
|
+
}
|
|
3844
4064
|
#selectNodeByIndex(nodeIndex, unselectOthers) {
|
|
3845
4065
|
this.#selectNode(this.#nodes[nodeIndex], unselectOthers);
|
|
3846
4066
|
}
|
|
@@ -3878,8 +4098,16 @@ var NodeSubsystem2 = class {
|
|
|
3878
4098
|
this.#nodeHovering = -1;
|
|
3879
4099
|
this.#boxSelectionNodes.Clear();
|
|
3880
4100
|
const selectedBox_Screenspace = this.#boxSelectionScreenspaceBox(camera);
|
|
4101
|
+
const canvas = {
|
|
4102
|
+
Position: { x: 0, y: 0 },
|
|
4103
|
+
Size: { x: ctx.canvas.width, y: ctx.canvas.height }
|
|
4104
|
+
};
|
|
3881
4105
|
for (let i = 0; i < this.#nodes.length; i++) {
|
|
3882
4106
|
let state = 0 /* Idle */;
|
|
4107
|
+
const nodeBounds = this.#nodes[i].calculateBounds(ctx, camera);
|
|
4108
|
+
if (!BoxIntersection(nodeBounds, canvas) && this.#nodes[i].layoutPortsWithoutDrawing(nodeBounds, camera.zoom)) {
|
|
4109
|
+
continue;
|
|
4110
|
+
}
|
|
3883
4111
|
if (mousePosition !== void 0 && !this.#boxSelect) {
|
|
3884
4112
|
const intersection = this.#nodes[i].inBounds(ctx, camera, mousePosition);
|
|
3885
4113
|
if (intersection.Node !== void 0 && intersection.PortIndex === void 0 && intersection.Widget === void 0) {
|
|
@@ -3900,8 +4128,8 @@ var NodeSubsystem2 = class {
|
|
|
3900
4128
|
};
|
|
3901
4129
|
}
|
|
3902
4130
|
} else if (this.#boxSelect) {
|
|
3903
|
-
const
|
|
3904
|
-
if (BoxIntersection(selectedBox_Screenspace,
|
|
4131
|
+
const nodeBounds2 = this.#nodes[i].calculateBounds(ctx, camera);
|
|
4132
|
+
if (BoxIntersection(selectedBox_Screenspace, nodeBounds2)) {
|
|
3905
4133
|
state = 1 /* MouseOver */;
|
|
3906
4134
|
this.#boxSelectionNodes.Push(i);
|
|
3907
4135
|
}
|
|
@@ -3923,12 +4151,16 @@ var NodeSubsystem2 = class {
|
|
|
3923
4151
|
render(ctx, camera, mousePosition) {
|
|
3924
4152
|
this.#lastCtx = ctx;
|
|
3925
4153
|
this.#cursor = "default" /* Default */;
|
|
4154
|
+
const awaitingLayout = this.#nodes.some((node) => !node.hasBeenLaidOut());
|
|
3926
4155
|
TimeExecution("Render_Connections", () => {
|
|
3927
4156
|
this.#renderConnections(ctx, camera, mousePosition);
|
|
3928
4157
|
});
|
|
3929
4158
|
TimeExecution("Render_Nodes", () => {
|
|
3930
4159
|
this.#renderNodes(ctx, camera, mousePosition);
|
|
3931
4160
|
});
|
|
4161
|
+
if (awaitingLayout) {
|
|
4162
|
+
requestRender();
|
|
4163
|
+
}
|
|
3932
4164
|
if (this.#boxSelect) {
|
|
3933
4165
|
const box = this.#boxSelectionScreenspaceBox(camera);
|
|
3934
4166
|
ctx.setLineDash([Theme.BoxSelect.LineDashLength]);
|
|
@@ -4204,6 +4436,7 @@ var FlowNode = class {
|
|
|
4204
4436
|
return;
|
|
4205
4437
|
}
|
|
4206
4438
|
this.#selected = true;
|
|
4439
|
+
requestRender();
|
|
4207
4440
|
for (let i = 0; i < this.#onSelect.length; i++) {
|
|
4208
4441
|
this.#onSelect[i]();
|
|
4209
4442
|
}
|
|
@@ -4249,6 +4482,7 @@ var FlowNode = class {
|
|
|
4249
4482
|
return;
|
|
4250
4483
|
}
|
|
4251
4484
|
this.#data[name] = value;
|
|
4485
|
+
requestRender();
|
|
4252
4486
|
for (let i = 0; i < this.#registeredAnyPropertyChangeCallbacks.length; i++) {
|
|
4253
4487
|
this.#registeredAnyPropertyChangeCallbacks[i](name, oldValue, value);
|
|
4254
4488
|
}
|
|
@@ -4509,6 +4743,7 @@ var FlowNode = class {
|
|
|
4509
4743
|
return;
|
|
4510
4744
|
}
|
|
4511
4745
|
this.#selected = false;
|
|
4746
|
+
requestRender();
|
|
4512
4747
|
for (let i = 0; i < this.#onUnselect.length; i++) {
|
|
4513
4748
|
this.#onUnselect[i]();
|
|
4514
4749
|
}
|
|
@@ -4538,6 +4773,7 @@ var FlowNode = class {
|
|
|
4538
4773
|
}
|
|
4539
4774
|
setPosition(position) {
|
|
4540
4775
|
CopyVector2(this.#position, position);
|
|
4776
|
+
requestRender();
|
|
4541
4777
|
}
|
|
4542
4778
|
getPosition() {
|
|
4543
4779
|
return this.#position;
|
|
@@ -4600,10 +4836,12 @@ var FlowNode = class {
|
|
|
4600
4836
|
}
|
|
4601
4837
|
addWidget(widget) {
|
|
4602
4838
|
this.#widgets.push(widget);
|
|
4839
|
+
requestRender();
|
|
4603
4840
|
}
|
|
4604
4841
|
insertWidget(index, widget) {
|
|
4605
4842
|
const at = Math.max(0, Math.min(index, this.#widgets.length));
|
|
4606
4843
|
this.#widgets.splice(at, 0, widget);
|
|
4844
|
+
requestRender();
|
|
4607
4845
|
}
|
|
4608
4846
|
removeWidget(widget) {
|
|
4609
4847
|
const index = this.#widgets.indexOf(widget, 0);
|
|
@@ -4611,12 +4849,15 @@ var FlowNode = class {
|
|
|
4611
4849
|
throw new Error("node does not contain widget");
|
|
4612
4850
|
}
|
|
4613
4851
|
this.#widgets.splice(index, 1);
|
|
4852
|
+
requestRender();
|
|
4614
4853
|
}
|
|
4615
4854
|
removeWidgetAt(index) {
|
|
4616
4855
|
if (index < 0 || index >= this.#widgets.length) {
|
|
4617
4856
|
return void 0;
|
|
4618
4857
|
}
|
|
4619
|
-
|
|
4858
|
+
const removed = this.#widgets.splice(index, 1)[0];
|
|
4859
|
+
requestRender();
|
|
4860
|
+
return removed;
|
|
4620
4861
|
}
|
|
4621
4862
|
moveWidget(from, to) {
|
|
4622
4863
|
if (from < 0 || from >= this.#widgets.length) {
|
|
@@ -4627,9 +4868,11 @@ var FlowNode = class {
|
|
|
4627
4868
|
}
|
|
4628
4869
|
const [widget] = this.#widgets.splice(from, 1);
|
|
4629
4870
|
this.#widgets.splice(to, 0, widget);
|
|
4871
|
+
requestRender();
|
|
4630
4872
|
}
|
|
4631
4873
|
clearWidgets() {
|
|
4632
4874
|
this.#widgets.length = 0;
|
|
4875
|
+
requestRender();
|
|
4633
4876
|
}
|
|
4634
4877
|
getWidget(index) {
|
|
4635
4878
|
return this.#widgets[index];
|
|
@@ -4701,6 +4944,7 @@ var FlowNode = class {
|
|
|
4701
4944
|
return;
|
|
4702
4945
|
}
|
|
4703
4946
|
this.#title.set(cleaned);
|
|
4947
|
+
requestRender();
|
|
4704
4948
|
for (let i = 0; i < this.#titleChangeCallback.length; i++) {
|
|
4705
4949
|
const callback = this.#titleChangeCallback[i];
|
|
4706
4950
|
callback(this, old, cleaned);
|
|
@@ -4719,6 +4963,7 @@ var FlowNode = class {
|
|
|
4719
4963
|
}
|
|
4720
4964
|
const old = this.#infoText;
|
|
4721
4965
|
this.#infoText = cleaned;
|
|
4966
|
+
requestRender();
|
|
4722
4967
|
for (let i = 0; i < this.#infoChangeCallback.length; i++) {
|
|
4723
4968
|
const callback = this.#infoChangeCallback[i];
|
|
4724
4969
|
callback(this, old, cleaned);
|
|
@@ -4758,7 +5003,12 @@ var FlowNode = class {
|
|
|
4758
5003
|
clearMessages() {
|
|
4759
5004
|
this.#messages = [];
|
|
4760
5005
|
}
|
|
5006
|
+
hasBeenLaidOut() {
|
|
5007
|
+
return this.#laidOut;
|
|
5008
|
+
}
|
|
5009
|
+
#laidOut = false;
|
|
4761
5010
|
render(ctx, camera, state, mousePosition, postProcess) {
|
|
5011
|
+
this.#laidOut = true;
|
|
4762
5012
|
VectorPool.run(() => {
|
|
4763
5013
|
const tempMeasurement = VectorPool.get();
|
|
4764
5014
|
this.#inputPortPositions.Clear();
|
|
@@ -4894,8 +5144,57 @@ var FlowNode = class {
|
|
|
4894
5144
|
const message = this.#messages[i];
|
|
4895
5145
|
messageStart.y += message.render(ctx, camera.zoom, messageStart, !(state === 0 /* Idle */)) + 10 * camera.zoom;
|
|
4896
5146
|
}
|
|
5147
|
+
this.#rememberPortOffsets(nodeBounds, camera.zoom);
|
|
4897
5148
|
});
|
|
4898
5149
|
}
|
|
5150
|
+
#portOffsets = { input: [], output: [] };
|
|
5151
|
+
#rememberPortOffsets(bounds, zoom) {
|
|
5152
|
+
if (zoom <= 0) {
|
|
5153
|
+
return;
|
|
5154
|
+
}
|
|
5155
|
+
const record = (positions, into) => {
|
|
5156
|
+
into.length = 0;
|
|
5157
|
+
for (let i = 0; i < positions.Count(); i++) {
|
|
5158
|
+
const box = positions.At(i);
|
|
5159
|
+
into.push({
|
|
5160
|
+
Position: {
|
|
5161
|
+
x: (box.Position.x - bounds.Position.x) / zoom,
|
|
5162
|
+
y: (box.Position.y - bounds.Position.y) / zoom
|
|
5163
|
+
},
|
|
5164
|
+
Size: {
|
|
5165
|
+
x: box.Size.x / zoom,
|
|
5166
|
+
y: box.Size.y / zoom
|
|
5167
|
+
}
|
|
5168
|
+
});
|
|
5169
|
+
}
|
|
5170
|
+
};
|
|
5171
|
+
record(this.#inputPortPositions, this.#portOffsets.input);
|
|
5172
|
+
record(this.#outputPortPositions, this.#portOffsets.output);
|
|
5173
|
+
}
|
|
5174
|
+
layoutPortsWithoutDrawing(bounds, zoom) {
|
|
5175
|
+
if (this.#portOffsets.input.length === 0 && this.#portOffsets.output.length === 0) {
|
|
5176
|
+
return false;
|
|
5177
|
+
}
|
|
5178
|
+
const project = (offsets, into) => {
|
|
5179
|
+
into.Clear();
|
|
5180
|
+
for (let i = 0; i < offsets.length; i++) {
|
|
5181
|
+
const offset = offsets[i];
|
|
5182
|
+
into.Push({
|
|
5183
|
+
Position: {
|
|
5184
|
+
x: bounds.Position.x + offset.Position.x * zoom,
|
|
5185
|
+
y: bounds.Position.y + offset.Position.y * zoom
|
|
5186
|
+
},
|
|
5187
|
+
Size: {
|
|
5188
|
+
x: offset.Size.x * zoom,
|
|
5189
|
+
y: offset.Size.y * zoom
|
|
5190
|
+
}
|
|
5191
|
+
});
|
|
5192
|
+
}
|
|
5193
|
+
};
|
|
5194
|
+
project(this.#portOffsets.input, this.#inputPortPositions);
|
|
5195
|
+
project(this.#portOffsets.output, this.#outputPortPositions);
|
|
5196
|
+
return true;
|
|
5197
|
+
}
|
|
4899
5198
|
};
|
|
4900
5199
|
|
|
4901
5200
|
// src/markdown/token.ts
|
|
@@ -5036,7 +5335,10 @@ function onFontsLoaded(callback) {
|
|
|
5036
5335
|
if (typeof document === "undefined" || document.fonts === void 0) {
|
|
5037
5336
|
return;
|
|
5038
5337
|
}
|
|
5039
|
-
document.fonts.addEventListener("loadingdone", () =>
|
|
5338
|
+
document.fonts.addEventListener("loadingdone", () => {
|
|
5339
|
+
callback();
|
|
5340
|
+
requestRender();
|
|
5341
|
+
});
|
|
5040
5342
|
}
|
|
5041
5343
|
var CodeBlockEntry = class {
|
|
5042
5344
|
#text;
|
|
@@ -5786,6 +6088,7 @@ var NoteSubsystem = class {
|
|
|
5786
6088
|
return;
|
|
5787
6089
|
}
|
|
5788
6090
|
this.#notes.push(note);
|
|
6091
|
+
requestRender();
|
|
5789
6092
|
for (let i = 0; i < this.#onNoteAddedCallbacks.length; i++) {
|
|
5790
6093
|
this.#onNoteAddedCallbacks[i](note);
|
|
5791
6094
|
}
|
|
@@ -5908,6 +6211,7 @@ var NoteSubsystem = class {
|
|
|
5908
6211
|
if (index > -1) {
|
|
5909
6212
|
const noteRemoved = this.#notes[index];
|
|
5910
6213
|
this.#notes.splice(index, 1);
|
|
6214
|
+
requestRender();
|
|
5911
6215
|
for (let i = 0; i < this.#onNoteRemovedCallbacks.length; i++) {
|
|
5912
6216
|
this.#onNoteRemovedCallbacks[i](noteRemoved);
|
|
5913
6217
|
}
|
|
@@ -6244,6 +6548,124 @@ var QuickMenu = class {
|
|
|
6244
6548
|
}
|
|
6245
6549
|
};
|
|
6246
6550
|
|
|
6551
|
+
// src/minimap.ts
|
|
6552
|
+
var Minimap = class {
|
|
6553
|
+
#enabled;
|
|
6554
|
+
#width;
|
|
6555
|
+
#height;
|
|
6556
|
+
#margin;
|
|
6557
|
+
#backgroundColor;
|
|
6558
|
+
#borderColor;
|
|
6559
|
+
#nodeColor;
|
|
6560
|
+
#viewportColor;
|
|
6561
|
+
#box = { Position: { x: 0, y: 0 }, Size: { x: 0, y: 0 } };
|
|
6562
|
+
#scale = 1;
|
|
6563
|
+
#originX = 0;
|
|
6564
|
+
#originY = 0;
|
|
6565
|
+
// The padding the last frame was laid out with, so a click maps back
|
|
6566
|
+
// through the same geometry it was drawn with.
|
|
6567
|
+
#padding = Theme.Minimap.Padding;
|
|
6568
|
+
#drawn = false;
|
|
6569
|
+
constructor(config) {
|
|
6570
|
+
this.#enabled = config?.enabled === true;
|
|
6571
|
+
this.#width = config?.width === void 0 ? 200 : config.width;
|
|
6572
|
+
this.#height = config?.height === void 0 ? 150 : config.height;
|
|
6573
|
+
this.#margin = config?.margin === void 0 ? 16 : config.margin;
|
|
6574
|
+
this.#backgroundColor = config?.backgroundColor;
|
|
6575
|
+
this.#borderColor = config?.borderColor;
|
|
6576
|
+
this.#nodeColor = config?.nodeColor;
|
|
6577
|
+
this.#viewportColor = config?.viewportColor;
|
|
6578
|
+
}
|
|
6579
|
+
enabled() {
|
|
6580
|
+
return this.#enabled;
|
|
6581
|
+
}
|
|
6582
|
+
setEnabled(enabled) {
|
|
6583
|
+
this.#enabled = enabled;
|
|
6584
|
+
this.#drawn = false;
|
|
6585
|
+
}
|
|
6586
|
+
contains(position) {
|
|
6587
|
+
return this.#enabled && this.#drawn && InBox(this.#box, position);
|
|
6588
|
+
}
|
|
6589
|
+
graphPositionOf(position, out) {
|
|
6590
|
+
out.x = (position.x - this.#box.Position.x - this.#padding) / this.#scale + this.#originX;
|
|
6591
|
+
out.y = (position.y - this.#box.Position.y - this.#padding) / this.#scale + this.#originY;
|
|
6592
|
+
}
|
|
6593
|
+
render(ctx, canvas, camera, nodes) {
|
|
6594
|
+
if (!this.#enabled) {
|
|
6595
|
+
this.#drawn = false;
|
|
6596
|
+
return;
|
|
6597
|
+
}
|
|
6598
|
+
const flat = new Camera();
|
|
6599
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
6600
|
+
const boxes = [];
|
|
6601
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
6602
|
+
const bounds = nodes[i].calculateBounds(ctx, flat);
|
|
6603
|
+
boxes.push(bounds);
|
|
6604
|
+
minX = Math.min(minX, bounds.Position.x);
|
|
6605
|
+
minY = Math.min(minY, bounds.Position.y);
|
|
6606
|
+
maxX = Math.max(maxX, bounds.Position.x + bounds.Size.x);
|
|
6607
|
+
maxY = Math.max(maxY, bounds.Position.y + bounds.Size.y);
|
|
6608
|
+
}
|
|
6609
|
+
const topLeft = { x: 0, y: 0 };
|
|
6610
|
+
const bottomRight = { x: 0, y: 0 };
|
|
6611
|
+
camera.screenSpaceToGraphSpace({ x: 0, y: 0 }, topLeft);
|
|
6612
|
+
camera.screenSpaceToGraphSpace({ x: canvas.width, y: canvas.height }, bottomRight);
|
|
6613
|
+
minX = Math.min(minX, topLeft.x);
|
|
6614
|
+
minY = Math.min(minY, topLeft.y);
|
|
6615
|
+
maxX = Math.max(maxX, bottomRight.x);
|
|
6616
|
+
maxY = Math.max(maxY, bottomRight.y);
|
|
6617
|
+
if (!isFinite(minX) || maxX <= minX || maxY <= minY) {
|
|
6618
|
+
this.#drawn = false;
|
|
6619
|
+
return;
|
|
6620
|
+
}
|
|
6621
|
+
this.#box.Size.x = this.#width;
|
|
6622
|
+
this.#box.Size.y = this.#height;
|
|
6623
|
+
this.#box.Position.x = canvas.width - this.#width - this.#margin;
|
|
6624
|
+
this.#box.Position.y = canvas.height - this.#height - this.#margin;
|
|
6625
|
+
this.#padding = Theme.Minimap.Padding;
|
|
6626
|
+
const usableWidth = this.#width - this.#padding * 2;
|
|
6627
|
+
const usableHeight = this.#height - this.#padding * 2;
|
|
6628
|
+
this.#scale = Math.min(usableWidth / (maxX - minX), usableHeight / (maxY - minY));
|
|
6629
|
+
this.#originX = minX;
|
|
6630
|
+
this.#originY = minY;
|
|
6631
|
+
const left = this.#box.Position.x + this.#padding;
|
|
6632
|
+
const top = this.#box.Position.y + this.#padding;
|
|
6633
|
+
const toMapX = (x) => left + (x - minX) * this.#scale;
|
|
6634
|
+
const toMapY = (y) => top + (y - minY) * this.#scale;
|
|
6635
|
+
ctx.fillStyle = this.#backgroundColor ?? Theme.Minimap.BackgroundColor;
|
|
6636
|
+
ctx.strokeStyle = this.#borderColor ?? Theme.Minimap.BorderColor;
|
|
6637
|
+
ctx.lineWidth = 1;
|
|
6638
|
+
ctx.beginPath();
|
|
6639
|
+
ctx.roundRect(
|
|
6640
|
+
this.#box.Position.x,
|
|
6641
|
+
this.#box.Position.y,
|
|
6642
|
+
this.#width,
|
|
6643
|
+
this.#height,
|
|
6644
|
+
Theme.Minimap.BorderRadius
|
|
6645
|
+
);
|
|
6646
|
+
ctx.fill();
|
|
6647
|
+
ctx.stroke();
|
|
6648
|
+
ctx.fillStyle = this.#nodeColor ?? Theme.Minimap.NodeColor;
|
|
6649
|
+
for (let i = 0; i < boxes.length; i++) {
|
|
6650
|
+
const b = boxes[i];
|
|
6651
|
+
ctx.fillRect(
|
|
6652
|
+
toMapX(b.Position.x),
|
|
6653
|
+
toMapY(b.Position.y),
|
|
6654
|
+
Math.max(1, b.Size.x * this.#scale),
|
|
6655
|
+
Math.max(1, b.Size.y * this.#scale)
|
|
6656
|
+
);
|
|
6657
|
+
}
|
|
6658
|
+
ctx.fillStyle = this.#viewportColor ?? Theme.Minimap.ViewportColor;
|
|
6659
|
+
ctx.fillRect(
|
|
6660
|
+
toMapX(topLeft.x),
|
|
6661
|
+
toMapY(topLeft.y),
|
|
6662
|
+
Math.max(1, (bottomRight.x - topLeft.x) * this.#scale),
|
|
6663
|
+
Math.max(1, (bottomRight.y - topLeft.y) * this.#scale)
|
|
6664
|
+
);
|
|
6665
|
+
this.#drawn = true;
|
|
6666
|
+
}
|
|
6667
|
+
};
|
|
6668
|
+
|
|
6247
6669
|
// src/graph.ts
|
|
6248
6670
|
function BuildBackgroundRenderer(backgroundColor) {
|
|
6249
6671
|
return (canvas, context, position, scale) => {
|
|
@@ -6381,7 +6803,13 @@ var NodeFlowGraph = class {
|
|
|
6381
6803
|
const backgroundColor = config?.backgroundColor === void 0 ? Theme.Graph.BackgroundColor : config.backgroundColor;
|
|
6382
6804
|
this.#backgroundRenderer = BuildBackgroundRenderer(backgroundColor);
|
|
6383
6805
|
}
|
|
6384
|
-
|
|
6806
|
+
this.#minimap = new Minimap(config?.minimap);
|
|
6807
|
+
this.#mainNodeSubsystem.setConnectionReleasedHandler((dangling) => {
|
|
6808
|
+
this.#openScopedMenu(dangling);
|
|
6809
|
+
});
|
|
6810
|
+
this.#watchCanvasSize();
|
|
6811
|
+
this.#stopRendering = onRenderRequested(this.#render.bind(this));
|
|
6812
|
+
requestRender();
|
|
6385
6813
|
new MouseObserver(
|
|
6386
6814
|
this.#canvas,
|
|
6387
6815
|
this.#mouseDragEvent.bind(this),
|
|
@@ -6399,39 +6827,90 @@ var NodeFlowGraph = class {
|
|
|
6399
6827
|
document.addEventListener(
|
|
6400
6828
|
"keydown",
|
|
6401
6829
|
(e) => {
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6830
|
+
this.#keyDown(e);
|
|
6831
|
+
requestRender();
|
|
6832
|
+
}
|
|
6833
|
+
);
|
|
6834
|
+
}
|
|
6835
|
+
#copyCallbacks = [];
|
|
6836
|
+
#pasteCallbacks = [];
|
|
6837
|
+
addCopyListener(callback) {
|
|
6838
|
+
this.#copyCallbacks.push(callback);
|
|
6839
|
+
}
|
|
6840
|
+
addPasteListener(callback) {
|
|
6841
|
+
this.#pasteCallbacks.push(callback);
|
|
6842
|
+
}
|
|
6843
|
+
#raiseCopy() {
|
|
6844
|
+
const nodes = this.#mainNodeSubsystem.getSelectedNodes();
|
|
6845
|
+
if (nodes.length === 0) {
|
|
6846
|
+
return;
|
|
6847
|
+
}
|
|
6848
|
+
const connections = this.#mainNodeSubsystem.connectionsWithin(nodes);
|
|
6849
|
+
this.#copyCallbacks.forEach((callback) => callback(nodes, connections));
|
|
6850
|
+
}
|
|
6851
|
+
#raisePaste() {
|
|
6852
|
+
const position = this.#mousePosition === void 0 ? { x: 0, y: 0 } : this.#sceenPositionToGraphPosition(this.#mousePosition);
|
|
6853
|
+
this.#pasteCallbacks.forEach((callback) => callback(position));
|
|
6854
|
+
}
|
|
6855
|
+
#deleteKey(e) {
|
|
6856
|
+
return e.code === "Delete" || e.code === "Backspace" || e.key === "Delete" || e.key === "Backspace";
|
|
6857
|
+
}
|
|
6858
|
+
#keyDown(e) {
|
|
6859
|
+
if (document.activeElement) {
|
|
6860
|
+
if (["INPUT", "TEXTAREA"].includes(document.activeElement.tagName)) return;
|
|
6861
|
+
}
|
|
6862
|
+
if (this.#deleteKey(e)) {
|
|
6863
|
+
if (this.#mainNodeSubsystem.getSelectedNodes().length > 0) {
|
|
6864
|
+
e.preventDefault();
|
|
6865
|
+
this.#mainNodeSubsystem.removeSelectedNodes();
|
|
6866
|
+
return;
|
|
6867
|
+
}
|
|
6868
|
+
}
|
|
6869
|
+
if (e.ctrlKey || e.metaKey) {
|
|
6870
|
+
const letter = e.code.startsWith("Key") ? e.code.substring(3).toLowerCase() : (e.key ?? "").toLowerCase();
|
|
6871
|
+
switch (letter) {
|
|
6872
|
+
case "c":
|
|
6873
|
+
this.#raiseCopy();
|
|
6416
6874
|
return;
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
if (!spacePressed) {
|
|
6875
|
+
case "v":
|
|
6876
|
+
this.#raisePaste();
|
|
6420
6877
|
return;
|
|
6421
|
-
|
|
6422
|
-
|
|
6878
|
+
// duplicate
|
|
6879
|
+
case "d":
|
|
6880
|
+
e.preventDefault();
|
|
6881
|
+
this.#raiseCopy();
|
|
6882
|
+
this.#raisePaste();
|
|
6423
6883
|
return;
|
|
6424
|
-
}
|
|
6425
|
-
const contextMenuPosition = this.#sceenPositionToGraphPosition(this.#mousePosition);
|
|
6426
|
-
let items = this.#mainNodeSubsystem.nodeFactory().newNodeSubmenus(this.#mainNodeSubsystem, contextMenuPosition);
|
|
6427
|
-
this.#openQuickMenu = {
|
|
6428
|
-
Menu: new QuickMenu({
|
|
6429
|
-
subMenus: items
|
|
6430
|
-
}),
|
|
6431
|
-
Position: contextMenuPosition
|
|
6432
|
-
};
|
|
6433
6884
|
}
|
|
6434
|
-
|
|
6885
|
+
}
|
|
6886
|
+
if (this.#openQuickMenu) {
|
|
6887
|
+
if (e.code === "Escape") {
|
|
6888
|
+
this.#openQuickMenu = null;
|
|
6889
|
+
return;
|
|
6890
|
+
}
|
|
6891
|
+
if (e.code === "Enter") {
|
|
6892
|
+
this.#openQuickMenu.Menu.execute();
|
|
6893
|
+
this.#openQuickMenu = null;
|
|
6894
|
+
return;
|
|
6895
|
+
}
|
|
6896
|
+
this.#openQuickMenu.Menu.keyboardEvent(e);
|
|
6897
|
+
return;
|
|
6898
|
+
}
|
|
6899
|
+
const spacePressed = e.key == " " || e.code == "Space";
|
|
6900
|
+
if (!spacePressed) {
|
|
6901
|
+
return;
|
|
6902
|
+
}
|
|
6903
|
+
if (!this.#mousePosition) {
|
|
6904
|
+
return;
|
|
6905
|
+
}
|
|
6906
|
+
const contextMenuPosition = this.#sceenPositionToGraphPosition(this.#mousePosition);
|
|
6907
|
+
let items = this.#mainNodeSubsystem.nodeFactory().newNodeSubmenus(this.#mainNodeSubsystem, contextMenuPosition);
|
|
6908
|
+
this.#openQuickMenu = {
|
|
6909
|
+
Menu: new QuickMenu({
|
|
6910
|
+
subMenus: items
|
|
6911
|
+
}),
|
|
6912
|
+
Position: contextMenuPosition
|
|
6913
|
+
};
|
|
6435
6914
|
}
|
|
6436
6915
|
#fileDrop(file) {
|
|
6437
6916
|
if (this.currentView().fileDrop(file)) {
|
|
@@ -6497,8 +6976,25 @@ var NodeFlowGraph = class {
|
|
|
6497
6976
|
this.#openQuickMenu = null;
|
|
6498
6977
|
this.#contextMenuEntryHovering = null;
|
|
6499
6978
|
this.#mousePosition = mousePosition;
|
|
6979
|
+
if (this.#minimap.contains(mousePosition)) {
|
|
6980
|
+
this.#lookAtFromMinimap(mousePosition);
|
|
6981
|
+
this.#draggingMinimap = true;
|
|
6982
|
+
return;
|
|
6983
|
+
}
|
|
6500
6984
|
this.currentView().clickStart(mousePosition, this.#camera, ctrlKey);
|
|
6501
6985
|
}
|
|
6986
|
+
#draggingMinimap = false;
|
|
6987
|
+
#lookAtFromMinimap(mousePosition) {
|
|
6988
|
+
const target = { x: 0, y: 0 };
|
|
6989
|
+
this.#minimap.graphPositionOf(mousePosition, target);
|
|
6990
|
+
this.#camera.position.x = -(target.x * this.#camera.zoom) + this.#canvas.width / 2;
|
|
6991
|
+
this.#camera.position.y = -(target.y * this.#camera.zoom) + this.#canvas.height / 2;
|
|
6992
|
+
requestRender();
|
|
6993
|
+
}
|
|
6994
|
+
/** The minimap, so it can be turned on and sized by the host. */
|
|
6995
|
+
minimap() {
|
|
6996
|
+
return this.#minimap;
|
|
6997
|
+
}
|
|
6502
6998
|
currentView() {
|
|
6503
6999
|
return this.#views[this.#currentView];
|
|
6504
7000
|
}
|
|
@@ -6518,6 +7014,12 @@ var NodeFlowGraph = class {
|
|
|
6518
7014
|
getSelectedNodes() {
|
|
6519
7015
|
return this.#mainNodeSubsystem.getSelectedNodes();
|
|
6520
7016
|
}
|
|
7017
|
+
unselectAllNodes() {
|
|
7018
|
+
this.#mainNodeSubsystem.unselectAllNodes();
|
|
7019
|
+
}
|
|
7020
|
+
removeSelectedNodes() {
|
|
7021
|
+
return this.#mainNodeSubsystem.removeSelectedNodes();
|
|
7022
|
+
}
|
|
6521
7023
|
/**
|
|
6522
7024
|
* Returns a copy of the current camera orientation (screen-space pan + zoom).
|
|
6523
7025
|
*/
|
|
@@ -6633,10 +7135,37 @@ var NodeFlowGraph = class {
|
|
|
6633
7135
|
Position: contextMenuPosition
|
|
6634
7136
|
};
|
|
6635
7137
|
}
|
|
7138
|
+
#openScopedMenu(dangling) {
|
|
7139
|
+
if (this.#mousePosition === void 0) {
|
|
7140
|
+
return;
|
|
7141
|
+
}
|
|
7142
|
+
const position = this.#sceenPositionToGraphPosition(this.#mousePosition);
|
|
7143
|
+
const menu = this.#mainNodeSubsystem.nodeFactory().openMenu(
|
|
7144
|
+
this.#mainNodeSubsystem,
|
|
7145
|
+
position,
|
|
7146
|
+
{
|
|
7147
|
+
needs: dangling.needs,
|
|
7148
|
+
types: dangling.types,
|
|
7149
|
+
onCreated: dangling.connectTo
|
|
7150
|
+
}
|
|
7151
|
+
);
|
|
7152
|
+
this.#openedContextMenu = {
|
|
7153
|
+
Menu: new ContextMenu(menu),
|
|
7154
|
+
Position: position
|
|
7155
|
+
};
|
|
7156
|
+
requestRender();
|
|
7157
|
+
}
|
|
6636
7158
|
#clickEnd() {
|
|
7159
|
+
this.#draggingMinimap = false;
|
|
6637
7160
|
this.currentView().clickEnd();
|
|
6638
7161
|
}
|
|
6639
7162
|
#mouseDragEvent(delta) {
|
|
7163
|
+
if (this.#draggingMinimap) {
|
|
7164
|
+
if (this.#mousePosition !== void 0) {
|
|
7165
|
+
this.#lookAtFromMinimap(this.#mousePosition);
|
|
7166
|
+
}
|
|
7167
|
+
return;
|
|
7168
|
+
}
|
|
6640
7169
|
let draggingSomething = this.currentView().mouseDragEvent(delta, this.#camera.zoom);
|
|
6641
7170
|
if (!draggingSomething) {
|
|
6642
7171
|
this.#camera.position.x += delta.x;
|
|
@@ -6645,12 +7174,45 @@ var NodeFlowGraph = class {
|
|
|
6645
7174
|
}
|
|
6646
7175
|
#lastFrameCursor;
|
|
6647
7176
|
#cursor;
|
|
6648
|
-
#
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
7177
|
+
#minimap;
|
|
7178
|
+
#stopRendering;
|
|
7179
|
+
#sizeObserver;
|
|
7180
|
+
#matchCanvasToParent() {
|
|
7181
|
+
const parent = this.#canvas.parentNode;
|
|
7182
|
+
if (parent === null) {
|
|
7183
|
+
return;
|
|
6653
7184
|
}
|
|
7185
|
+
const rect = parent.getBoundingClientRect();
|
|
7186
|
+
if (this.#canvas.width === rect.width && this.#canvas.height === rect.height) {
|
|
7187
|
+
return;
|
|
7188
|
+
}
|
|
7189
|
+
this.#canvas.width = rect.width;
|
|
7190
|
+
this.#canvas.height = rect.height;
|
|
7191
|
+
}
|
|
7192
|
+
#watchCanvasSize() {
|
|
7193
|
+
this.#matchCanvasToParent();
|
|
7194
|
+
const parent = this.#canvas.parentNode;
|
|
7195
|
+
if (parent === null || typeof ResizeObserver === "undefined") {
|
|
7196
|
+
return;
|
|
7197
|
+
}
|
|
7198
|
+
this.#sizeObserver = new ResizeObserver(() => {
|
|
7199
|
+
this.#matchCanvasToParent();
|
|
7200
|
+
requestRender();
|
|
7201
|
+
});
|
|
7202
|
+
this.#sizeObserver.observe(parent);
|
|
7203
|
+
}
|
|
7204
|
+
requestRender() {
|
|
7205
|
+
requestRender();
|
|
7206
|
+
}
|
|
7207
|
+
renderContinuously() {
|
|
7208
|
+
return renderContinuously();
|
|
7209
|
+
}
|
|
7210
|
+
dispose() {
|
|
7211
|
+
this.#stopRendering();
|
|
7212
|
+
this.#sizeObserver?.disconnect();
|
|
7213
|
+
}
|
|
7214
|
+
#render() {
|
|
7215
|
+
this.#matchCanvasToParent();
|
|
6654
7216
|
this.#cursor = "default" /* Default */;
|
|
6655
7217
|
TimeExecution("Render_Background", this.#renderBackground.bind(this));
|
|
6656
7218
|
TimeExecution("Render_View_" + this.#currentView, () => {
|
|
@@ -6659,13 +7221,15 @@ var NodeFlowGraph = class {
|
|
|
6659
7221
|
this.#cursor = results?.cursorStyle;
|
|
6660
7222
|
}
|
|
6661
7223
|
});
|
|
7224
|
+
TimeExecution("Render_Minimap", () => {
|
|
7225
|
+
this.#minimap.render(this.#ctx, this.#canvas, this.#camera, this.#mainNodeSubsystem.getNodes());
|
|
7226
|
+
});
|
|
6662
7227
|
TimeExecution("Render_Context", this.#renderContextMenu.bind(this));
|
|
6663
7228
|
TimeExecution("Render_QuickMenu", this.#renderQuickMenu.bind(this));
|
|
6664
7229
|
if (this.#lastFrameCursor !== this.#cursor) {
|
|
6665
7230
|
this.#canvas.style.cursor = this.#cursor;
|
|
6666
7231
|
}
|
|
6667
7232
|
this.#lastFrameCursor = this.#cursor;
|
|
6668
|
-
window.requestAnimationFrame(this.#render.bind(this));
|
|
6669
7233
|
}
|
|
6670
7234
|
#renderBackground() {
|
|
6671
7235
|
this.#backgroundRenderer(this.#canvas, this.#ctx, this.#camera.position, this.#camera.zoom);
|
|
@@ -6706,6 +7270,7 @@ export {
|
|
|
6706
7270
|
GlobalWidgetFactory,
|
|
6707
7271
|
ImageWidget,
|
|
6708
7272
|
MessageType,
|
|
7273
|
+
Minimap,
|
|
6709
7274
|
NodeFactory,
|
|
6710
7275
|
NodeFlowGraph,
|
|
6711
7276
|
NodeState,
|
|
@@ -6719,6 +7284,10 @@ export {
|
|
|
6719
7284
|
Theme,
|
|
6720
7285
|
ToggleWidget,
|
|
6721
7286
|
WidgetFactory,
|
|
6722
|
-
|
|
7287
|
+
portConfigTypes,
|
|
7288
|
+
portsCompatible,
|
|
7289
|
+
renderContinuously,
|
|
7290
|
+
requestRender,
|
|
7291
|
+
typeSetsCompatible
|
|
6723
7292
|
};
|
|
6724
7293
|
//# sourceMappingURL=index.mjs.map
|