@elicdavis/node-flow 0.2.1 → 0.2.2

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.
@@ -0,0 +1,102 @@
1
+ import { strict as assert } from 'assert';
2
+ import { NodeSubsystem } from '../src/nodes/subsystem';
3
+ import { PassSubsystem } from '../src/pass/subsystem';
4
+ import { FlowNode, NodeIntersection } from '../src/node';
5
+ import { Camera } from '../src/camera';
6
+ import { stubCtx } from './support';
7
+
8
+ function scene(inputs: Array<{ name: string, type: string, hidden?: boolean }>) {
9
+ const graph = new NodeSubsystem(new PassSubsystem());
10
+ const node = new FlowNode({
11
+ title: 'material',
12
+ position: { x: 100, y: 100 },
13
+ inputs,
14
+ outputs: [{ name: 'Out', type: 'material' }],
15
+ });
16
+ graph.addNode(node);
17
+ return { graph, node, camera: new Camera(), ctx: stubCtx() };
18
+ }
19
+
20
+ const material = [
21
+ { name: 'Color', type: 'color' },
22
+ { name: 'Sheen', type: 'sheen', hidden: true },
23
+ { name: 'Clearcoat', type: 'clearcoat', hidden: true },
24
+ ];
25
+
26
+ function findWidget(s: ReturnType<typeof scene>): NodeIntersection | undefined {
27
+ s.graph.render(s.ctx, s.camera, undefined);
28
+ const bounds = s.node.calculateBounds(s.ctx, s.camera);
29
+ for (let y = bounds.Position.y; y < bounds.Position.y + bounds.Size.y; y++) {
30
+ const hit = s.node.inBounds(s.ctx, s.camera, { x: bounds.Position.x + bounds.Size.x / 2, y });
31
+ if (hit.Widget !== undefined) {
32
+ return hit;
33
+ }
34
+ }
35
+ return undefined;
36
+ }
37
+
38
+ function click(hit: NodeIntersection) {
39
+ const pointer = { position: { x: 0, y: 0 }, inside: true } as any;
40
+ hit.Widget!.PointerDown!(pointer);
41
+ hit.Widget!.PointerUp!(pointer);
42
+ }
43
+
44
+ describe('a node with hidden ports', () => {
45
+ it('draws a row that shows them', () => {
46
+ const s = scene(material);
47
+ const toggle = findWidget(s);
48
+ assert.ok(toggle, 'no toggle row to click');
49
+
50
+ click(toggle);
51
+
52
+ assert.equal(s.node.inputPort(1).hidden(), false);
53
+ assert.equal(s.node.inputPort(2).hidden(), false);
54
+ });
55
+
56
+ it('hides them again on a second click', () => {
57
+ const s = scene(material);
58
+ click(findWidget(s)!);
59
+ click(findWidget(s)!);
60
+
61
+ assert.equal(s.node.inputPort(1).hidden(), true);
62
+ assert.equal(s.node.inputPort(2).hidden(), true);
63
+ });
64
+
65
+ it('grows when they are shown', () => {
66
+ const s = scene(material);
67
+ const collapsed = s.node.calculateBounds(s.ctx, s.camera).Size.y;
68
+
69
+ s.node.setHiddenPortsShown(true);
70
+
71
+ assert.ok(s.node.calculateBounds(s.ctx, s.camera).Size.y > collapsed);
72
+ });
73
+
74
+ it('asks for a fresh layout when they are shown', () => {
75
+ const s = scene(material);
76
+ s.graph.render(s.ctx, s.camera, undefined);
77
+
78
+ s.node.setHiddenPortsShown(true);
79
+
80
+ assert.ok(!s.node.hasBeenLaidOut());
81
+ });
82
+
83
+ it('does not take the place of its own widgets', () => {
84
+ const s = scene(material);
85
+ assert.equal(s.node.widgetCount(), 0);
86
+ assert.equal(findWidget(s)!.WidgetIndex, undefined);
87
+ });
88
+
89
+ it('has no row when nothing is hidden', () => {
90
+ assert.equal(findWidget(scene([{ name: 'Color', type: 'color' }])), undefined);
91
+ });
92
+
93
+ it('has no row once every hidden port is wired', () => {
94
+ const s = scene([{ name: 'Color', type: 'color' }, { name: 'Sheen', type: 'sheen', hidden: true }]);
95
+ const source = new FlowNode({ title: 'sheen', outputs: [{ name: 'Out', type: 'sheen' }] });
96
+ s.graph.addNode(source);
97
+
98
+ s.graph.connectNodes(source, 0, s.node, 1);
99
+
100
+ assert.equal(findWidget(s), undefined);
101
+ });
102
+ });
@@ -0,0 +1,78 @@
1
+ import { strict as assert } from 'assert';
2
+ import { MouseObserver } from '../src/input';
3
+
4
+ function observe(run: (fire: (name: string, event: any) => void, zoom: () => number) => void) {
5
+ const listeners = new Map<string, Array<(e: any) => void>>();
6
+ const ele: any = {
7
+ style: {},
8
+ clientHeight: 600,
9
+ addEventListener: (name: string, fn: (e: any) => void) => {
10
+ listeners.set(name, [...(listeners.get(name) ?? []), fn]);
11
+ },
12
+ getBoundingClientRect: () => ({ left: 0, top: 0 }),
13
+ };
14
+ const fire = (name: string, event: any) => {
15
+ event.preventDefault = () => { };
16
+ (listeners.get(name) ?? []).forEach((fn) => fn(event));
17
+ };
18
+
19
+ let zoom = 1;
20
+ const g = globalThis as any;
21
+ const previous = { document: g.document, WheelEvent: g.WheelEvent };
22
+ g.document = { addEventListener: () => { } };
23
+ g.WheelEvent = { DOM_DELTA_PIXEL: 0, DOM_DELTA_LINE: 1, DOM_DELTA_PAGE: 2 };
24
+ try {
25
+ new MouseObserver(ele, () => { }, () => { }, () => { }, () => { }, () => { }, () => { },
26
+ (factor) => { zoom *= factor; });
27
+ run(fire, () => zoom);
28
+ } finally {
29
+ g.document = previous.document;
30
+ g.WheelEvent = previous.WheelEvent;
31
+ }
32
+ }
33
+
34
+ function fingers(apart: number) {
35
+ return { touches: [{ clientX: 300 - apart / 2, clientY: 300 }, { clientX: 300 + apart / 2, clientY: 300 }] };
36
+ }
37
+
38
+ describe('pinch to zoom', () => {
39
+ it('doubles the zoom when the fingers spread to twice as far apart', () => {
40
+ observe((fire, zoom) => {
41
+ fire('touchstart', fingers(100));
42
+ fire('touchmove', fingers(125));
43
+ fire('touchmove', fingers(150));
44
+ fire('touchmove', fingers(200));
45
+
46
+ assert.ok(Math.abs(zoom() - 2) < 1e-9, `zoom was ${zoom()}`);
47
+ });
48
+ });
49
+
50
+ it('halves the zoom when the fingers close to half as far apart', () => {
51
+ observe((fire, zoom) => {
52
+ fire('touchstart', fingers(300));
53
+ fire('touchmove', fingers(200));
54
+ fire('touchmove', fingers(150));
55
+
56
+ assert.ok(Math.abs(zoom() - 0.5) < 1e-9, `zoom was ${zoom()}`);
57
+ });
58
+ });
59
+ });
60
+
61
+ describe('the scroll wheel', () => {
62
+ it('zooms in scrolling up and out scrolling down', () => {
63
+ observe((fire, zoom) => {
64
+ fire('wheel', { deltaY: -100, deltaMode: 0, clientX: 0, clientY: 0 });
65
+ assert.ok(zoom() > 1);
66
+
67
+ fire('wheel', { deltaY: 200, deltaMode: 0, clientX: 0, clientY: 0 });
68
+ assert.ok(zoom() < 1);
69
+ });
70
+ });
71
+
72
+ it('never flips the zoom however far a page scroll goes', () => {
73
+ observe((fire, zoom) => {
74
+ fire('wheel', { deltaY: 10, deltaMode: 2, clientX: 0, clientY: 0 });
75
+ assert.ok(zoom() > 0);
76
+ });
77
+ });
78
+ });