@elicdavis/node-flow 0.1.13 → 0.1.15
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 +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +56 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +56 -24
- package/dist/index.mjs.map +1 -1
- package/index.html +30 -0
- package/package.json +1 -1
- package/src/camera.ts +23 -1
- package/src/graph.ts +23 -1
- package/src/node.ts +26 -25
package/index.html
CHANGED
|
@@ -312,10 +312,40 @@ node.addOutput({ name: "sum", type: "float32" })
|
|
|
312
312
|
],
|
|
313
313
|
});
|
|
314
314
|
|
|
315
|
+
const manyPortsNode = new FlowNode({
|
|
316
|
+
position: {
|
|
317
|
+
x: 1200,
|
|
318
|
+
y: 450
|
|
319
|
+
},
|
|
320
|
+
title: "Many Ports",
|
|
321
|
+
subTitle: "Zoom stress test",
|
|
322
|
+
info: "Node with lots of ports — zoom in/out to check height stability",
|
|
323
|
+
inputs: [
|
|
324
|
+
{ name: "in 0", type: "float32" },
|
|
325
|
+
{ name: "in 1", type: "float32" },
|
|
326
|
+
{ name: "in 2", type: "float32" },
|
|
327
|
+
{ name: "in 3", type: "float32" },
|
|
328
|
+
{ name: "in 4", type: "float32" },
|
|
329
|
+
{ name: "in 5", type: "float32" },
|
|
330
|
+
{ name: "in 6", type: "float32" },
|
|
331
|
+
{ name: "in 7", type: "float32" },
|
|
332
|
+
{ name: "in 8", type: "float32" },
|
|
333
|
+
{ name: "in 9", type: "float32" },
|
|
334
|
+
],
|
|
335
|
+
outputs: [
|
|
336
|
+
{ name: "out 0", type: "float32" },
|
|
337
|
+
{ name: "out 1", type: "float32" },
|
|
338
|
+
{ name: "out 2", type: "float32" },
|
|
339
|
+
{ name: "out 3", type: "float32" },
|
|
340
|
+
{ name: "out 4", type: "float32" },
|
|
341
|
+
],
|
|
342
|
+
});
|
|
343
|
+
|
|
315
344
|
graph.addNode(sumNode)
|
|
316
345
|
graph.addNode(aNode)
|
|
317
346
|
graph.addNode(bNode)
|
|
318
347
|
graph.addNode(arrNode)
|
|
348
|
+
graph.addNode(manyPortsNode)
|
|
319
349
|
|
|
320
350
|
graph.connectNodes(aNode, 0, sumNode, 0)
|
|
321
351
|
graph.connectNodes(bNode, 0, sumNode, 1)
|
package/package.json
CHANGED
package/src/camera.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { Vector2, Zero } from "./types/vector2";
|
|
2
2
|
|
|
3
|
+
/** Serializable camera orientation for save/restore. */
|
|
4
|
+
export interface CameraOrientation {
|
|
5
|
+
position: Vector2;
|
|
6
|
+
zoom: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
export class Camera {
|
|
4
10
|
|
|
5
11
|
zoom: number;
|
|
@@ -22,9 +28,25 @@ export class Camera {
|
|
|
22
28
|
out.y = this.position.y + (graphPosition.y * this.zoom);
|
|
23
29
|
}
|
|
24
30
|
|
|
31
|
+
getOrientation(): CameraOrientation {
|
|
32
|
+
return {
|
|
33
|
+
position: {
|
|
34
|
+
x: this.position.x,
|
|
35
|
+
y: this.position.y,
|
|
36
|
+
},
|
|
37
|
+
zoom: this.zoom,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
setOrientation(orientation: CameraOrientation): void {
|
|
42
|
+
this.position.x = orientation.position.x;
|
|
43
|
+
this.position.y = orientation.position.y;
|
|
44
|
+
this.zoom = orientation.zoom;
|
|
45
|
+
}
|
|
46
|
+
|
|
25
47
|
reset(): void {
|
|
26
48
|
this.zoom = 1;
|
|
27
49
|
this.position.x = 0;
|
|
28
50
|
this.position.y = 0;
|
|
29
51
|
}
|
|
30
|
-
}
|
|
52
|
+
}
|
package/src/graph.ts
CHANGED
|
@@ -14,7 +14,8 @@ import { ConnectionRendererConfiguration, NodeAddedCallback, NodeRemovedCallback
|
|
|
14
14
|
import { Connection } from './connection';
|
|
15
15
|
import { Publisher } from './nodes/publisher';
|
|
16
16
|
import { VectorPool } from './types/pool';
|
|
17
|
-
import { Camera } from './camera';
|
|
17
|
+
import { Camera, CameraOrientation } from './camera';
|
|
18
|
+
export { CameraOrientation };
|
|
18
19
|
import { PassSubsystem } from './pass/subsystem';
|
|
19
20
|
import { QuickMenu } from './quickMenu';
|
|
20
21
|
|
|
@@ -388,6 +389,27 @@ export class NodeFlowGraph {
|
|
|
388
389
|
return this.#mainNodeSubsystem.getSelectedNodes();
|
|
389
390
|
}
|
|
390
391
|
|
|
392
|
+
/**
|
|
393
|
+
* Returns a copy of the current camera orientation (screen-space pan + zoom).
|
|
394
|
+
*/
|
|
395
|
+
getCamera(): CameraOrientation {
|
|
396
|
+
return this.#camera.getOrientation();
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Restores a previously saved camera orientation.
|
|
401
|
+
*/
|
|
402
|
+
setCamera(orientation: CameraOrientation): void {
|
|
403
|
+
this.#camera.setOrientation(orientation);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Resets the camera to the default orientation (origin, zoom 1).
|
|
408
|
+
*/
|
|
409
|
+
resetCamera(): void {
|
|
410
|
+
this.#camera.reset();
|
|
411
|
+
}
|
|
412
|
+
|
|
391
413
|
/**
|
|
392
414
|
* Adjusts camera position and zoom so all nodes fit in view (~10% padding).
|
|
393
415
|
* Falls back to camera.reset() when there are no nodes.
|
package/src/node.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Port, PortConfig, PortType } from "./port";
|
|
2
2
|
import { FontWeight, TextStyle, TextStyleConfig, TextStyleFallback } from "./styles/text";
|
|
3
3
|
import { Box, InBox } from "./types/box";
|
|
4
|
-
import { CopyVector2, Distance, Vector2, Zero } from "./types/vector2";
|
|
4
|
+
import { CopyVector2, Distance, ScaleVector, Vector2, Zero } from "./types/vector2";
|
|
5
5
|
import { Widget } from './widgets/widget';
|
|
6
6
|
import { List } from './types/list';
|
|
7
7
|
import { BoxStyle, BoxStyleConfig, BoxStyleWithFallback } from "./styles/box";
|
|
@@ -784,56 +784,55 @@ export class FlowNode {
|
|
|
784
784
|
|
|
785
785
|
public calculateBounds(ctx: CanvasRenderingContext2D, camera: Camera): Box {
|
|
786
786
|
const tempMeasurement = Zero();
|
|
787
|
-
|
|
788
|
-
const
|
|
789
|
-
const doubleScaledPadding = scaledPadding * 2;
|
|
790
|
-
const scaledElementSpacing = this.#elementSpacing * zoom;
|
|
787
|
+
|
|
788
|
+
const doublePadding = this.#padding * 2;
|
|
791
789
|
|
|
792
790
|
const screenSpacePosition = Zero();
|
|
793
791
|
camera.graphSpaceToScreenSpace(this.#position, screenSpacePosition);
|
|
794
792
|
|
|
795
793
|
const size = Zero();
|
|
796
|
-
this.#title.size(ctx,
|
|
794
|
+
this.#title.size(ctx, 1, size);
|
|
797
795
|
|
|
798
796
|
const subtitleSize = Zero();
|
|
799
|
-
this.#subTitle.size(ctx,
|
|
797
|
+
this.#subTitle.size(ctx, 1, subtitleSize);
|
|
800
798
|
size.x = Math.max(size.x, subtitleSize.x);
|
|
801
799
|
|
|
802
800
|
if (this.#infoText !== "") {
|
|
803
801
|
size.x += (size.y * 4);
|
|
804
802
|
}
|
|
805
803
|
|
|
806
|
-
size.x +=
|
|
807
|
-
size.y +=
|
|
804
|
+
size.x += doublePadding;
|
|
805
|
+
size.y += doublePadding + (this.#elementSpacing * this.#input.length);
|
|
808
806
|
|
|
809
807
|
for (let i = 0; i < this.#input.length; i++) {
|
|
810
808
|
const port = this.#input[i];
|
|
811
|
-
this.#portTextStyle.measure(ctx,
|
|
809
|
+
this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
|
|
812
810
|
size.y += tempMeasurement.y;
|
|
813
|
-
size.x = Math.max(size.x, tempMeasurement.x +
|
|
811
|
+
size.x = Math.max(size.x, tempMeasurement.x + doublePadding)
|
|
814
812
|
}
|
|
815
813
|
|
|
816
|
-
size.y += (
|
|
814
|
+
size.y += (this.#elementSpacing * this.#output.length);
|
|
817
815
|
|
|
818
816
|
for (let i = 0; i < this.#output.length; i++) {
|
|
819
817
|
const port = this.#output[i];
|
|
820
|
-
this.#portTextStyle.measure(ctx,
|
|
818
|
+
this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
|
|
821
819
|
size.y += tempMeasurement.y;
|
|
822
|
-
size.x = Math.max(size.x, tempMeasurement.x +
|
|
820
|
+
size.x = Math.max(size.x, tempMeasurement.x + doublePadding)
|
|
823
821
|
}
|
|
824
822
|
|
|
825
|
-
size.y += (
|
|
823
|
+
size.y += (this.#elementSpacing * this.#widgets.length);
|
|
826
824
|
for (let i = 0; i < this.#widgets.length; i++) {
|
|
827
825
|
const element = this.#widgets[i];
|
|
828
826
|
const eleSize = element.Size();
|
|
829
|
-
size.y += eleSize.y
|
|
830
|
-
size.x = Math.max(size.x, (eleSize.x
|
|
827
|
+
size.y += eleSize.y
|
|
828
|
+
size.x = Math.max(size.x, (eleSize.x) + doublePadding)
|
|
831
829
|
}
|
|
832
830
|
|
|
833
831
|
// Add some padding at the end!
|
|
834
|
-
size.y +=
|
|
832
|
+
size.y += this.#elementSpacing
|
|
835
833
|
|
|
836
|
-
size.x = Math.max(size.x, MINIMUM_NODE_WIDTH
|
|
834
|
+
size.x = Math.max(size.x, MINIMUM_NODE_WIDTH)
|
|
835
|
+
ScaleVector(size, camera.zoom);
|
|
837
836
|
|
|
838
837
|
return {
|
|
839
838
|
Position: screenSpacePosition,
|
|
@@ -1161,11 +1160,12 @@ export class FlowNode {
|
|
|
1161
1160
|
for (let i = 0; i < this.#input.length; i++) {
|
|
1162
1161
|
ctx.textAlign = TextAlign.Left;
|
|
1163
1162
|
const port = this.#input[i];
|
|
1164
|
-
this.#portTextStyle.measure(ctx,
|
|
1163
|
+
this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
|
|
1164
|
+
const portHeight = tempMeasurement.y * camera.zoom;
|
|
1165
1165
|
const position = VectorPool.get();
|
|
1166
1166
|
|
|
1167
1167
|
position.x = nodeBounds.Position.x;
|
|
1168
|
-
position.y = startY + (
|
|
1168
|
+
position.y = startY + (portHeight / 2);
|
|
1169
1169
|
|
|
1170
1170
|
// Text
|
|
1171
1171
|
this.#portTextStyle.setupStyle(ctx, camera.zoom);
|
|
@@ -1174,7 +1174,7 @@ export class FlowNode {
|
|
|
1174
1174
|
// Port
|
|
1175
1175
|
this.#inputPortPositions.Push(port.render(ctx, position, camera, mousePosition, postProcess));
|
|
1176
1176
|
|
|
1177
|
-
startY +=
|
|
1177
|
+
startY += portHeight + scaledElementSpacing;
|
|
1178
1178
|
}
|
|
1179
1179
|
|
|
1180
1180
|
// Output Ports
|
|
@@ -1182,10 +1182,11 @@ export class FlowNode {
|
|
|
1182
1182
|
ctx.textAlign = TextAlign.Right;
|
|
1183
1183
|
for (let i = 0; i < this.#output.length; i++) {
|
|
1184
1184
|
const port = this.#output[i];
|
|
1185
|
-
this.#portTextStyle.measure(ctx,
|
|
1185
|
+
this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
|
|
1186
|
+
const portHeight = tempMeasurement.y * camera.zoom;
|
|
1186
1187
|
const position = VectorPool.get();
|
|
1187
1188
|
position.x = rightSide;
|
|
1188
|
-
position.y = startY + (
|
|
1189
|
+
position.y = startY + (portHeight / 2);
|
|
1189
1190
|
|
|
1190
1191
|
// Text
|
|
1191
1192
|
this.#portTextStyle.setupStyle(ctx, camera.zoom);
|
|
@@ -1194,7 +1195,7 @@ export class FlowNode {
|
|
|
1194
1195
|
// Port
|
|
1195
1196
|
this.#outputPortPositions.Push(port.render(ctx, position, camera, mousePosition, postProcess));
|
|
1196
1197
|
|
|
1197
|
-
startY +=
|
|
1198
|
+
startY += portHeight + scaledElementSpacing;
|
|
1198
1199
|
}
|
|
1199
1200
|
|
|
1200
1201
|
// Widgets
|