@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/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
- const zoom = camera.zoom;
788
- const scaledPadding = this.#padding * zoom;
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, zoom, size);
794
+ this.#title.size(ctx, 1, size);
797
795
 
798
796
  const subtitleSize = Zero();
799
- this.#subTitle.size(ctx, zoom, subtitleSize);
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 += doubleScaledPadding;
807
- size.y += doubleScaledPadding + (scaledElementSpacing * this.#input.length);
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, zoom, port.getDisplayName(), tempMeasurement);
809
+ this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
812
810
  size.y += tempMeasurement.y;
813
- size.x = Math.max(size.x, tempMeasurement.x + doubleScaledPadding)
811
+ size.x = Math.max(size.x, tempMeasurement.x + doublePadding)
814
812
  }
815
813
 
816
- size.y += (scaledElementSpacing * this.#output.length);
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, zoom, port.getDisplayName(), tempMeasurement);
818
+ this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
821
819
  size.y += tempMeasurement.y;
822
- size.x = Math.max(size.x, tempMeasurement.x + doubleScaledPadding)
820
+ size.x = Math.max(size.x, tempMeasurement.x + doublePadding)
823
821
  }
824
822
 
825
- size.y += (scaledElementSpacing * this.#widgets.length);
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 * zoom;
830
- size.x = Math.max(size.x, (eleSize.x * zoom) + doubleScaledPadding)
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 += scaledElementSpacing
832
+ size.y += this.#elementSpacing
835
833
 
836
- size.x = Math.max(size.x, MINIMUM_NODE_WIDTH * zoom)
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, camera.zoom, port.getDisplayName(), tempMeasurement);
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 + (tempMeasurement.y / 2);
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 += tempMeasurement.y + scaledElementSpacing;
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, camera.zoom, port.getDisplayName(), tempMeasurement);
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 + (tempMeasurement.y / 2);
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 += tempMeasurement.y + scaledElementSpacing;
1233
+ startY += portHeight + scaledElementSpacing;
1198
1234
  }
1199
1235
 
1200
1236
  // Widgets
@@ -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.getDataType() !== conn.outPort()?.getDataType()) {
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.getDataType() !== conn.inPort()?.getDataType()) {
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 outType = nodeOut.outputPort(outPort).getDataType();
381
- const inType = nodeIn.inputPort(inPort).getDataType();
382
- if (outType !== inType) {
383
- console.error("can't connect nodes of different types", outType, inType);
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