-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
node.ts
137 lines (120 loc) · 4.37 KB
/
node.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
* Sigma.js WebGL Abstract Node Program
* =====================================
*
* @module
*/
import { Attributes } from "graphology-types";
import Sigma from "../sigma";
import { NodeDisplayData, NonEmptyArray, RenderParams } from "../types";
import { indexToColor } from "../utils";
import { NodeHoverDrawingFunction } from "./node-hover";
import { NodeLabelDrawingFunction } from "./node-labels";
import { AbstractProgram, Program } from "./program";
export abstract class AbstractNodeProgram<
N extends Attributes = Attributes,
E extends Attributes = Attributes,
G extends Attributes = Attributes,
> extends AbstractProgram<N, E, G> {
abstract drawLabel: NodeLabelDrawingFunction<N, E, G> | undefined;
abstract drawHover: NodeHoverDrawingFunction<N, E, G> | undefined;
abstract process(nodeIndex: number, offset: number, data: NodeDisplayData): void;
}
export abstract class NodeProgram<
Uniform extends string = string,
N extends Attributes = Attributes,
E extends Attributes = Attributes,
G extends Attributes = Attributes,
>
extends Program<Uniform, N, E, G>
implements AbstractNodeProgram<N, E, G>
{
drawLabel: NodeLabelDrawingFunction<N, E, G> | undefined;
drawHover: NodeHoverDrawingFunction<N, E, G> | undefined;
kill(): void {
super.kill();
}
process(nodeIndex: number, offset: number, data: NodeDisplayData): void {
let i = offset * this.STRIDE;
// NOTE: dealing with hidden items automatically
if (data.hidden) {
for (let l = i + this.STRIDE; i < l; i++) {
this.array[i] = 0;
}
return;
}
return this.processVisibleItem(indexToColor(nodeIndex), i, data);
}
abstract processVisibleItem(nodeIndex: number, i: number, data: NodeDisplayData): void;
}
class NodeProgramClass<
N extends Attributes = Attributes,
E extends Attributes = Attributes,
G extends Attributes = Attributes,
> implements AbstractNodeProgram<N, E, G>
{
constructor(_gl: WebGLRenderingContext, _pickingBuffer: WebGLFramebuffer | null, _renderer: Sigma<N, E, G>) {
return this;
}
drawLabel: NodeLabelDrawingFunction<N, E, G> | undefined;
drawHover: NodeHoverDrawingFunction<N, E, G> | undefined;
kill(): void {
return undefined;
}
reallocate(_capacity: number): void {
return undefined;
}
process(_nodeIndex: number, _offset: number, _data: NodeDisplayData): void {
return undefined;
}
render(_params: RenderParams): void {
return undefined;
}
}
export type NodeProgramType<
N extends Attributes = Attributes,
E extends Attributes = Attributes,
G extends Attributes = Attributes,
> = typeof NodeProgramClass<N, E, G>;
/**
* Helper function combining two or more programs into a single compound one.
* Note that this is more a quick & easy way to combine program than a really
* performant option. More performant programs can be written entirely.
*
* @param {array} programClasses - Program classes to combine.
* @param {function} drawLabel - An optional node "draw label" function.
* @param {function} drawHover - An optional node "draw hover" function.
* @return {function}
*/
export function createNodeCompoundProgram<
N extends Attributes = Attributes,
E extends Attributes = Attributes,
G extends Attributes = Attributes,
>(
programClasses: NonEmptyArray<NodeProgramType<N, E, G>>,
drawLabel?: NodeLabelDrawingFunction<N, E, G>,
drawHover?: NodeLabelDrawingFunction<N, E, G>,
): NodeProgramType<N, E, G> {
return class NodeCompoundProgram implements AbstractNodeProgram<N, E, G> {
programs: NonEmptyArray<AbstractNodeProgram<N, E, G>>;
constructor(gl: WebGLRenderingContext, pickingBuffer: WebGLFramebuffer | null, renderer: Sigma<N, E, G>) {
this.programs = programClasses.map((Program) => {
return new Program(gl, pickingBuffer, renderer);
}) as unknown as NonEmptyArray<AbstractNodeProgram<N, E, G>>;
}
drawLabel = drawLabel;
drawHover = drawHover;
reallocate(capacity: number): void {
this.programs.forEach((program) => program.reallocate(capacity));
}
process(nodeIndex: number, offset: number, data: NodeDisplayData): void {
this.programs.forEach((program) => program.process(nodeIndex, offset, data));
}
render(params: RenderParams): void {
this.programs.forEach((program) => program.render(params));
}
kill(): void {
this.programs.forEach((program) => program.kill());
}
};
}