@elicdavis/node-flow 0.1.1 → 0.1.3
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/README.md +19 -5
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +728 -674
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +728 -674
- package/dist/index.mjs.map +1 -1
- package/esbuild.ts +1 -1
- package/index.html +16 -12
- package/package.json +1 -1
- package/src/elements/base.ts +1 -0
- package/src/elements/text.ts +32 -4
- package/src/port.ts +54 -17
package/esbuild.ts
CHANGED
package/index.html
CHANGED
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
}
|
|
28
28
|
</style>
|
|
29
29
|
|
|
30
|
-
<script src="./dist/
|
|
30
|
+
<script src="./dist/web/NodeFlow.js" type="module"></script>
|
|
31
31
|
</head>
|
|
32
32
|
|
|
33
33
|
<body>
|
|
34
34
|
<canvas id="canvas"></canvas>
|
|
35
35
|
<script type="module">
|
|
36
|
-
import { Theme, FlowNode, NodeFlowGraph, FlowNote } from "./dist/
|
|
36
|
+
import { Theme, FlowNode, NodeFlowGraph, FlowNote } from "./dist/web/NodeFlow.js";
|
|
37
37
|
|
|
38
38
|
const canvas = document.getElementById("canvas");
|
|
39
39
|
Theme.FontFamily = "Source Code Pro";
|
|
@@ -203,7 +203,11 @@ let node = new FlowNode({
|
|
|
203
203
|
{ name: "b", type: "float32" }
|
|
204
204
|
],
|
|
205
205
|
outputs: [
|
|
206
|
-
{
|
|
206
|
+
{
|
|
207
|
+
name: "sum",
|
|
208
|
+
type: "float32",
|
|
209
|
+
description: "The sum of a and b"
|
|
210
|
+
}
|
|
207
211
|
],
|
|
208
212
|
});
|
|
209
213
|
graph.addNode(node);
|
|
@@ -221,8 +225,8 @@ node.addOutput({ name: "sum", type: "float32" })
|
|
|
221
225
|
|
|
222
226
|
var sumNode = new FlowNode({
|
|
223
227
|
position: {
|
|
224
|
-
x:
|
|
225
|
-
y:
|
|
228
|
+
x: 750,
|
|
229
|
+
y: 700
|
|
226
230
|
},
|
|
227
231
|
title: "Add",
|
|
228
232
|
info: "I add two numbers",
|
|
@@ -231,14 +235,14 @@ node.addOutput({ name: "sum", type: "float32" })
|
|
|
231
235
|
{ name: "b", type: "float32" }
|
|
232
236
|
],
|
|
233
237
|
outputs: [
|
|
234
|
-
{ name: "sum", type: "float32" }
|
|
238
|
+
{ name: "sum", type: "float32", description: "The sum of a and b" }
|
|
235
239
|
],
|
|
236
240
|
});
|
|
237
241
|
|
|
238
242
|
|
|
239
243
|
var aNode = new FlowNode({
|
|
240
244
|
position: {
|
|
241
|
-
x:
|
|
245
|
+
x: 450,
|
|
242
246
|
y: 500
|
|
243
247
|
},
|
|
244
248
|
title: "Number",
|
|
@@ -256,7 +260,7 @@ node.addOutput({ name: "sum", type: "float32" })
|
|
|
256
260
|
|
|
257
261
|
var bNode = new FlowNode({
|
|
258
262
|
position: {
|
|
259
|
-
x:
|
|
263
|
+
x: 450,
|
|
260
264
|
y: 650
|
|
261
265
|
},
|
|
262
266
|
title: "Number",
|
|
@@ -280,17 +284,17 @@ node.addOutput({ name: "sum", type: "float32" })
|
|
|
280
284
|
|
|
281
285
|
const arrNode = new FlowNode({
|
|
282
286
|
position: {
|
|
283
|
-
x:
|
|
284
|
-
y:
|
|
287
|
+
x: 950,
|
|
288
|
+
y: 700
|
|
285
289
|
},
|
|
286
290
|
title: "Add",
|
|
287
291
|
subTitle: "Array Inputs",
|
|
288
292
|
info: "This node contains a port that can take multiple input nodes at once, which can be useful for operations that can operate on [0,n] data sizes",
|
|
289
293
|
inputs: [
|
|
290
|
-
{ name: "numbers", type: "float32", array: true },
|
|
294
|
+
{ name: "numbers", type: "float32", array: true, description: "All numbers to add together" },
|
|
291
295
|
],
|
|
292
296
|
outputs: [
|
|
293
|
-
{ name: "sum", type: "float32" }
|
|
297
|
+
{ name: "sum", type: "float32", description: "The sum of all connected nodes to our 'numbers' port" }
|
|
294
298
|
],
|
|
295
299
|
});
|
|
296
300
|
|
package/package.json
CHANGED
package/src/elements/base.ts
CHANGED
|
@@ -107,6 +107,7 @@ export abstract class RenderElementBase implements IRenderElement {
|
|
|
107
107
|
this.doRender(ctx, offsetPosition, graphScale, elementSize);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
// todo: Remove limitations argument?
|
|
110
111
|
abstract calcSize(ctx: CanvasRenderingContext2D, out: Vector2, limitations: Vector2): void;
|
|
111
112
|
|
|
112
113
|
protected maxLimitations(out: Vector2): void {
|
package/src/elements/text.ts
CHANGED
|
@@ -17,6 +17,7 @@ export enum VerticalAlign {
|
|
|
17
17
|
export interface TextElementStyling extends RenderElementBaseStyling {
|
|
18
18
|
Align?: TextAlign
|
|
19
19
|
VerticalAlign?: VerticalAlign
|
|
20
|
+
LineHeight?: number
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export class TextElement extends RenderElementBase {
|
|
@@ -26,16 +27,19 @@ export class TextElement extends RenderElementBase {
|
|
|
26
27
|
|
|
27
28
|
#verticalAlign: VerticalAlign;
|
|
28
29
|
|
|
30
|
+
#lineHeight: number;
|
|
31
|
+
|
|
29
32
|
constructor(text: Text, styling?: TextElementStyling) {
|
|
30
33
|
super(styling);
|
|
31
34
|
this.#text = text;
|
|
32
35
|
this.#align = styling?.Align ?? TextAlign.Left;
|
|
33
36
|
this.#verticalAlign = styling?.VerticalAlign ?? VerticalAlign.Top;
|
|
37
|
+
this.#lineHeight = styling?.LineHeight ?? 1;
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
doRender(ctx: CanvasRenderingContext2D, position: Vector2, graphScale: number, scaledFillableSpace: Vector2): void {
|
|
37
41
|
const scale = Zero();
|
|
38
|
-
this.calcSize(ctx, scale);
|
|
42
|
+
this.calcSize(ctx, scale, scaledFillableSpace);
|
|
39
43
|
ScaleVector(scale, graphScale);
|
|
40
44
|
|
|
41
45
|
const justifiedPosition = Zero();
|
|
@@ -77,10 +81,34 @@ export class TextElement extends RenderElementBase {
|
|
|
77
81
|
default:
|
|
78
82
|
throw new Error("unimplemented justification: " + this.#align);
|
|
79
83
|
}
|
|
80
|
-
|
|
84
|
+
|
|
85
|
+
if (scaledFillableSpace.x <= 0) {
|
|
86
|
+
this.#text.render(ctx, graphScale, justifiedPosition);
|
|
87
|
+
} else {
|
|
88
|
+
const eles = this.#text.breakIntoLines(ctx, scaledFillableSpace.x);
|
|
89
|
+
|
|
90
|
+
const tempSize = { x: 0, y: 0 };
|
|
91
|
+
for (let i = 0; i < eles.length; i++) {
|
|
92
|
+
eles[i].render(ctx, graphScale, justifiedPosition);
|
|
93
|
+
eles[i].size(ctx, 1, tempSize)
|
|
94
|
+
justifiedPosition.y += this.#text.style().getSize() * this.#lineHeight
|
|
95
|
+
}
|
|
96
|
+
}
|
|
81
97
|
}
|
|
82
98
|
|
|
83
|
-
calcSize(ctx: CanvasRenderingContext2D, out: Vector2): void {
|
|
84
|
-
|
|
99
|
+
calcSize(ctx: CanvasRenderingContext2D, out: Vector2, limitations: Vector2): void {
|
|
100
|
+
if (limitations.x <= 0) {
|
|
101
|
+
this.#text.size(ctx, 1, out);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const eles = this.#text.breakIntoLines(ctx, limitations.x);
|
|
106
|
+
const tempSize = { x: 0, y: 0 };
|
|
107
|
+
out.x = 0;
|
|
108
|
+
out.y = this.#text.style().getSize() * eles.length * this.#lineHeight;
|
|
109
|
+
for (let i = 0; i < eles.length; i++) {
|
|
110
|
+
eles[i].size(ctx, 1, tempSize)
|
|
111
|
+
out.x = Math.max(tempSize.x, out.x);
|
|
112
|
+
}
|
|
85
113
|
}
|
|
86
114
|
}
|
package/src/port.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { Camera } from "./camera";
|
|
2
2
|
import { Connection } from './connection';
|
|
3
|
+
import { RenderElementBase } from "./elements/base";
|
|
4
|
+
import { ContainerRenderElement, AlignItems } from './elements/container';
|
|
5
|
+
import { TextAlign, TextElement } from "./elements/text";
|
|
3
6
|
import { FlowNode } from "./node";
|
|
4
7
|
import { PassSubsystem } from "./pass/subsystem";
|
|
5
|
-
import {
|
|
6
|
-
import { Box,
|
|
8
|
+
import { FontStyle } from "./styles/text";
|
|
9
|
+
import { Box, InBox } from "./types/box";
|
|
10
|
+
import { Text } from "./types/text";
|
|
7
11
|
import { Vector2 } from "./types/vector2";
|
|
8
|
-
import { Color, HSV, HSV2RGB, RgbToHex } from
|
|
12
|
+
import { Color, HSV, HSV2RGB, RgbToHex } from './utils/color';
|
|
9
13
|
|
|
10
14
|
export enum PortType {
|
|
11
15
|
Input = "INPUT",
|
|
@@ -25,6 +29,7 @@ type ConnectionChangeCallback = (connection: Connection, connectionIndex: number
|
|
|
25
29
|
export interface PortConfig {
|
|
26
30
|
name?: string;
|
|
27
31
|
type?: string;
|
|
32
|
+
description?: string;
|
|
28
33
|
array?: boolean;
|
|
29
34
|
emptyStyle?: PortStyle;
|
|
30
35
|
filledStyle?: PortStyle;
|
|
@@ -64,9 +69,11 @@ export class Port {
|
|
|
64
69
|
|
|
65
70
|
#dataType: string;
|
|
66
71
|
|
|
72
|
+
#dataTypePopupElement: RenderElementBase;
|
|
73
|
+
|
|
67
74
|
#onConnectionAdded: Array<ConnectionChangeCallback>;
|
|
68
75
|
|
|
69
|
-
#onConnectionRemoved: Array<ConnectionChangeCallback
|
|
76
|
+
#onConnectionRemoved: Array<ConnectionChangeCallback>;
|
|
70
77
|
|
|
71
78
|
constructor(node: FlowNode, portType: PortType, config?: PortConfig) {
|
|
72
79
|
this.#node = node;
|
|
@@ -98,6 +105,44 @@ export class Port {
|
|
|
98
105
|
if (config?.onConnectionRemoved) {
|
|
99
106
|
this.#onConnectionRemoved.push(config?.onConnectionRemoved);
|
|
100
107
|
}
|
|
108
|
+
|
|
109
|
+
const containerElements = new Array<RenderElementBase>();
|
|
110
|
+
let dataTypeDisplay = this.#dataType;
|
|
111
|
+
if (config?.array === true) {
|
|
112
|
+
dataTypeDisplay = "Array<" + dataTypeDisplay + ">"
|
|
113
|
+
}
|
|
114
|
+
containerElements.push(new TextElement(
|
|
115
|
+
new Text(dataTypeDisplay, {
|
|
116
|
+
color: "white",
|
|
117
|
+
}),
|
|
118
|
+
{
|
|
119
|
+
Align: TextAlign.Center,
|
|
120
|
+
}
|
|
121
|
+
));
|
|
122
|
+
|
|
123
|
+
const description = config?.description;
|
|
124
|
+
if (description && description !== "") {
|
|
125
|
+
containerElements.push(new TextElement(
|
|
126
|
+
new Text(description, { color: "white", style: FontStyle.Italic }),
|
|
127
|
+
{
|
|
128
|
+
Align: TextAlign.Center,
|
|
129
|
+
Padding: { Top: 16 },
|
|
130
|
+
MaxWidth: 400,
|
|
131
|
+
LineHeight: 1.5
|
|
132
|
+
}
|
|
133
|
+
));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
this.#dataTypePopupElement = new ContainerRenderElement(
|
|
137
|
+
containerElements,
|
|
138
|
+
{
|
|
139
|
+
BackgroundColor: "rgba(0, 0, 0, 0.75)",
|
|
140
|
+
Border: {
|
|
141
|
+
Radius: 6,
|
|
142
|
+
},
|
|
143
|
+
Padding: 13,
|
|
144
|
+
}
|
|
145
|
+
);
|
|
101
146
|
}
|
|
102
147
|
|
|
103
148
|
addConnection(connection: Connection): void {
|
|
@@ -183,20 +228,12 @@ export class Port {
|
|
|
183
228
|
const xPos = position.x;
|
|
184
229
|
const yPos = position.y;
|
|
185
230
|
|
|
231
|
+
// TODO: Make it so we're not creating a new lambda each frame
|
|
186
232
|
postProcess.queue(() => {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const w = measurement.width + (padding * camera.zoom);
|
|
192
|
-
|
|
193
|
-
ctx.beginPath();
|
|
194
|
-
ctx.fillStyle = "rgba(0, 0, 0, 0.75)";
|
|
195
|
-
ctx.roundRect(xPos - w / 2, yPos + (scaledRadius * 3) - (padding * camera.zoom), w, (padding * 2) * camera.zoom, 4 * camera.zoom);
|
|
196
|
-
ctx.fill();
|
|
197
|
-
|
|
198
|
-
ctx.fillStyle = "#FFFFFF";
|
|
199
|
-
ctx.fillText(this.#dataType, xPos, yPos + (scaledRadius * 3));
|
|
233
|
+
const size = { x: 0, y: 0 }
|
|
234
|
+
this.#dataTypePopupElement.calcSize(ctx, size, { x: -1, y: -1 });
|
|
235
|
+
// size.x = Math.min(150, size.x)
|
|
236
|
+
this.#dataTypePopupElement.render(ctx, { x: xPos - (size.x / 2), y: yPos }, 1, size)
|
|
200
237
|
})
|
|
201
238
|
}
|
|
202
239
|
|