@elicdavis/node-flow 0.1.14 → 0.1.16
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/.mocharc.json +5 -0
- package/dist/index.d.mts +62 -1
- package/dist/index.d.ts +62 -1
- package/dist/index.js +3197 -3337
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3189 -3337
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
- package/src/graph.ts +7 -0
- package/src/index.ts +66 -40
- package/src/markdown/entry.ts +21 -2
- package/src/markdown/lexicalParser.ts +22 -32
- package/src/markdown/syntaxParser.ts +93 -68
- package/src/node.ts +61 -25
- package/src/nodes/subsystem.ts +7 -7
- package/src/organize.ts +276 -181
- package/src/port.ts +130 -7
- package/src/styles/text.ts +8 -0
- package/src/types/text.ts +6 -4
- package/src/utils/string.ts +7 -1
- package/src/widgets/color.ts +5 -6
- package/src/widgets/factory.ts +1 -1
- package/src/widgets/number.ts +2 -2
- package/src/widgets/slider.ts +2 -2
- package/src/widgets/string.ts +2 -2
- package/src/widgets/toggle.ts +2 -2
- package/src/widgets/widget.ts +22 -0
- package/test/markdown.test.ts +165 -0
- package/test/organize.test.ts +156 -0
- package/test/port.test.ts +125 -0
- package/tsconfig.json +6 -2
- package/dist/web/NodeFlow.js +0 -8
- package/dist/web/NodeFlow.js.map +0 -7
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,
|
|
@@ -857,6 +856,11 @@ export class FlowNode {
|
|
|
857
856
|
this.#widgets.push(widget);
|
|
858
857
|
}
|
|
859
858
|
|
|
859
|
+
insertWidget(index: number, widget: Widget): void {
|
|
860
|
+
const at = Math.max(0, Math.min(index, this.#widgets.length));
|
|
861
|
+
this.#widgets.splice(at, 0, widget);
|
|
862
|
+
}
|
|
863
|
+
|
|
860
864
|
removeWidget(widget: Widget): void {
|
|
861
865
|
const index = this.#widgets.indexOf(widget, 0);
|
|
862
866
|
if (index === -1) {
|
|
@@ -865,10 +869,40 @@ export class FlowNode {
|
|
|
865
869
|
this.#widgets.splice(index, 1);
|
|
866
870
|
}
|
|
867
871
|
|
|
872
|
+
removeWidgetAt(index: number): Widget | undefined {
|
|
873
|
+
if (index < 0 || index >= this.#widgets.length) {
|
|
874
|
+
return undefined;
|
|
875
|
+
}
|
|
876
|
+
return this.#widgets.splice(index, 1)[0];
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
moveWidget(from: number, to: number): void {
|
|
880
|
+
if (from < 0 || from >= this.#widgets.length) {
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
if (to < 0 || to >= this.#widgets.length || from === to) {
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
const [widget] = this.#widgets.splice(from, 1);
|
|
887
|
+
this.#widgets.splice(to, 0, widget);
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
clearWidgets(): void {
|
|
891
|
+
this.#widgets.length = 0;
|
|
892
|
+
}
|
|
893
|
+
|
|
868
894
|
getWidget(index: number): Widget {
|
|
869
895
|
return this.#widgets[index];
|
|
870
896
|
}
|
|
871
897
|
|
|
898
|
+
widgets(): ReadonlyArray<Widget> {
|
|
899
|
+
return this.#widgets;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
indexOfWidget(widget: Widget): number {
|
|
903
|
+
return this.#widgets.indexOf(widget, 0);
|
|
904
|
+
}
|
|
905
|
+
|
|
872
906
|
widgetCount(): number {
|
|
873
907
|
return this.#widgets.length;
|
|
874
908
|
}
|
|
@@ -1161,11 +1195,12 @@ export class FlowNode {
|
|
|
1161
1195
|
for (let i = 0; i < this.#input.length; i++) {
|
|
1162
1196
|
ctx.textAlign = TextAlign.Left;
|
|
1163
1197
|
const port = this.#input[i];
|
|
1164
|
-
this.#portTextStyle.measure(ctx,
|
|
1198
|
+
this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
|
|
1199
|
+
const portHeight = tempMeasurement.y * camera.zoom;
|
|
1165
1200
|
const position = VectorPool.get();
|
|
1166
1201
|
|
|
1167
1202
|
position.x = nodeBounds.Position.x;
|
|
1168
|
-
position.y = startY + (
|
|
1203
|
+
position.y = startY + (portHeight / 2);
|
|
1169
1204
|
|
|
1170
1205
|
// Text
|
|
1171
1206
|
this.#portTextStyle.setupStyle(ctx, camera.zoom);
|
|
@@ -1174,7 +1209,7 @@ export class FlowNode {
|
|
|
1174
1209
|
// Port
|
|
1175
1210
|
this.#inputPortPositions.Push(port.render(ctx, position, camera, mousePosition, postProcess));
|
|
1176
1211
|
|
|
1177
|
-
startY +=
|
|
1212
|
+
startY += portHeight + scaledElementSpacing;
|
|
1178
1213
|
}
|
|
1179
1214
|
|
|
1180
1215
|
// Output Ports
|
|
@@ -1182,10 +1217,11 @@ export class FlowNode {
|
|
|
1182
1217
|
ctx.textAlign = TextAlign.Right;
|
|
1183
1218
|
for (let i = 0; i < this.#output.length; i++) {
|
|
1184
1219
|
const port = this.#output[i];
|
|
1185
|
-
this.#portTextStyle.measure(ctx,
|
|
1220
|
+
this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
|
|
1221
|
+
const portHeight = tempMeasurement.y * camera.zoom;
|
|
1186
1222
|
const position = VectorPool.get();
|
|
1187
1223
|
position.x = rightSide;
|
|
1188
|
-
position.y = startY + (
|
|
1224
|
+
position.y = startY + (portHeight / 2);
|
|
1189
1225
|
|
|
1190
1226
|
// Text
|
|
1191
1227
|
this.#portTextStyle.setupStyle(ctx, camera.zoom);
|
|
@@ -1194,7 +1230,7 @@ export class FlowNode {
|
|
|
1194
1230
|
// Port
|
|
1195
1231
|
this.#outputPortPositions.Push(port.render(ctx, position, camera, mousePosition, postProcess));
|
|
1196
1232
|
|
|
1197
|
-
startY +=
|
|
1233
|
+
startY += portHeight + scaledElementSpacing;
|
|
1198
1234
|
}
|
|
1199
1235
|
|
|
1200
1236
|
// Widgets
|
package/src/nodes/subsystem.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { FlowNode, NodeState } from "../node";
|
|
|
6
6
|
import { Organize } from "../organize";
|
|
7
7
|
import { PassSubsystem } from "../pass/subsystem";
|
|
8
8
|
import { TimeExecution } from "../performance";
|
|
9
|
-
import { Port, PortType } from "../port";
|
|
9
|
+
import { Port, PortType, portsCompatible } from "../port";
|
|
10
10
|
import { BoxStyle } from "../styles/box";
|
|
11
11
|
import { CursorStyle } from "../styles/cursor";
|
|
12
12
|
import { Theme } from "../theme";
|
|
@@ -341,13 +341,13 @@ export class NodeSubsystem {
|
|
|
341
341
|
}
|
|
342
342
|
|
|
343
343
|
// Different types, can't connect
|
|
344
|
-
if (this.#portHovering.InputPort && this.#portHovering.Port
|
|
344
|
+
if (this.#portHovering.InputPort && !portsCompatible(this.#portHovering.Port, conn.outPort())) {
|
|
345
345
|
this.#clearCurrentlySelectedConnection();
|
|
346
346
|
return;
|
|
347
347
|
}
|
|
348
348
|
|
|
349
349
|
// Different types, can't connect
|
|
350
|
-
if (!this.#portHovering.InputPort && this.#portHovering.Port
|
|
350
|
+
if (!this.#portHovering.InputPort && !portsCompatible(this.#portHovering.Port, conn.inPort())) {
|
|
351
351
|
this.#clearCurrentlySelectedConnection();
|
|
352
352
|
return;
|
|
353
353
|
}
|
|
@@ -377,10 +377,10 @@ export class NodeSubsystem {
|
|
|
377
377
|
}
|
|
378
378
|
|
|
379
379
|
connectNodes(nodeOut: FlowNode, outPort: number, nodeIn: FlowNode, inPort: number): Connection | undefined {
|
|
380
|
-
const
|
|
381
|
-
const
|
|
382
|
-
if (
|
|
383
|
-
console.error("can't connect nodes of different types",
|
|
380
|
+
const from = nodeOut.outputPort(outPort);
|
|
381
|
+
const to = nodeIn.inputPort(inPort);
|
|
382
|
+
if (!portsCompatible(from, to)) {
|
|
383
|
+
console.error("can't connect nodes of different types", from.getDataType(), to.getDataType());
|
|
384
384
|
return;
|
|
385
385
|
}
|
|
386
386
|
|