@onerjs/smart-filters 8.25.0

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.
Files changed (66) hide show
  1. package/license.md +21 -0
  2. package/package.json +52 -0
  3. package/readme.md +9 -0
  4. package/src/IDisposable.ts +9 -0
  5. package/src/blockFoundation/aggregateBlock.ts +148 -0
  6. package/src/blockFoundation/baseBlock.ts +339 -0
  7. package/src/blockFoundation/customAggregateBlock.ts +88 -0
  8. package/src/blockFoundation/customShaderBlock.ts +362 -0
  9. package/src/blockFoundation/disableableShaderBlock.ts +91 -0
  10. package/src/blockFoundation/index.ts +9 -0
  11. package/src/blockFoundation/inputBlock.deserializer.ts +72 -0
  12. package/src/blockFoundation/inputBlock.serialization.types.ts +126 -0
  13. package/src/blockFoundation/inputBlock.serializer.ts +150 -0
  14. package/src/blockFoundation/inputBlock.ts +181 -0
  15. package/src/blockFoundation/outputBlock.ts +144 -0
  16. package/src/blockFoundation/shaderBlock.ts +156 -0
  17. package/src/blockFoundation/textureOptions.ts +57 -0
  18. package/src/command/command.ts +59 -0
  19. package/src/command/commandBuffer.ts +71 -0
  20. package/src/command/commandBufferDebugger.ts +14 -0
  21. package/src/command/index.ts +7 -0
  22. package/src/connection/connectionPoint.ts +205 -0
  23. package/src/connection/connectionPointCompatibilityState.ts +31 -0
  24. package/src/connection/connectionPointDirection.ts +9 -0
  25. package/src/connection/connectionPointType.ts +45 -0
  26. package/src/connection/connectionPointWithDefault.ts +27 -0
  27. package/src/connection/index.ts +8 -0
  28. package/src/editorUtils/editableInPropertyPage.ts +106 -0
  29. package/src/editorUtils/index.ts +3 -0
  30. package/src/index.ts +16 -0
  31. package/src/optimization/dependencyGraph.ts +96 -0
  32. package/src/optimization/index.ts +1 -0
  33. package/src/optimization/optimizedShaderBlock.ts +131 -0
  34. package/src/optimization/smartFilterOptimizer.ts +757 -0
  35. package/src/runtime/index.ts +8 -0
  36. package/src/runtime/renderTargetGenerator.ts +222 -0
  37. package/src/runtime/shaderRuntime.ts +174 -0
  38. package/src/runtime/smartFilterRuntime.ts +112 -0
  39. package/src/runtime/strongRef.ts +18 -0
  40. package/src/serialization/importCustomBlockDefinition.ts +86 -0
  41. package/src/serialization/index.ts +10 -0
  42. package/src/serialization/serializedBlockDefinition.ts +12 -0
  43. package/src/serialization/serializedShaderBlockDefinition.ts +7 -0
  44. package/src/serialization/serializedSmartFilter.ts +6 -0
  45. package/src/serialization/smartFilterDeserializer.ts +190 -0
  46. package/src/serialization/smartFilterSerializer.ts +110 -0
  47. package/src/serialization/v1/defaultBlockSerializer.ts +21 -0
  48. package/src/serialization/v1/index.ts +4 -0
  49. package/src/serialization/v1/shaderBlockSerialization.types.ts +85 -0
  50. package/src/serialization/v1/smartFilterSerialization.types.ts +129 -0
  51. package/src/smartFilter.ts +255 -0
  52. package/src/utils/buildTools/buildShaders.ts +14 -0
  53. package/src/utils/buildTools/convertGlslIntoBlock.ts +370 -0
  54. package/src/utils/buildTools/convertGlslIntoShaderProgram.ts +173 -0
  55. package/src/utils/buildTools/convertShaders.ts +65 -0
  56. package/src/utils/buildTools/recordVersionNumber.js +24 -0
  57. package/src/utils/buildTools/shaderCode.types.ts +59 -0
  58. package/src/utils/buildTools/shaderConverter.ts +466 -0
  59. package/src/utils/buildTools/watchShaders.ts +44 -0
  60. package/src/utils/index.ts +4 -0
  61. package/src/utils/renderTargetUtils.ts +30 -0
  62. package/src/utils/shaderCodeUtils.ts +192 -0
  63. package/src/utils/textureLoaders.ts +31 -0
  64. package/src/utils/textureUtils.ts +28 -0
  65. package/src/utils/uniqueIdGenerator.ts +28 -0
  66. package/src/version.ts +4 -0
@@ -0,0 +1,362 @@
1
+ import { Logger } from "core/Misc/logger.js";
2
+ import type { Effect } from "core/Materials/effect.js";
3
+ import { ConnectionPointType, type ConnectionPointValue } from "../connection/connectionPointType.js";
4
+ import { ShaderBinding } from "../runtime/shaderRuntime.js";
5
+ import { CreateStrongRef } from "../runtime/strongRef.js";
6
+ import type { SerializedShaderBlockDefinition } from "../serialization/serializedShaderBlockDefinition.js";
7
+ import type { SerializedInputConnectionPointV1 } from "../serialization/v1/shaderBlockSerialization.types.js";
8
+ import type { SmartFilter } from "../smartFilter.js";
9
+ import type { ShaderProgram } from "../utils/shaderCodeUtils.js";
10
+ import { ShaderBlock } from "./shaderBlock.js";
11
+ import type { RuntimeData } from "../connection/connectionPoint.js";
12
+ import type { Nullable } from "core/types.js";
13
+
14
+ /**
15
+ * The binding for a CustomShaderBlock
16
+ */
17
+ class CustomShaderBlockBinding extends ShaderBinding {
18
+ private readonly _bindSteps: ((effect: Effect, width: number, height: number) => void)[] = [];
19
+
20
+ /**
21
+ * Creates a new shader binding instance for the CustomShaderBlock block.
22
+ * @param inputsWithRuntimeData - The input connection points of the block
23
+ */
24
+ public constructor(inputsWithRuntimeData: AnyInputWithRuntimeData[]) {
25
+ super();
26
+
27
+ for (const input of inputsWithRuntimeData) {
28
+ switch (input.type) {
29
+ case ConnectionPointType.Float:
30
+ this._bindSteps.push((effect) => {
31
+ effect.setFloat(this.getRemappedName(input.name), input.runtimeData.value);
32
+ });
33
+ break;
34
+ case ConnectionPointType.Texture:
35
+ this._bindSteps.push((effect) => {
36
+ effect.setTexture(this.getRemappedName(input.name), input.runtimeData.value);
37
+ });
38
+ break;
39
+ case ConnectionPointType.Color3:
40
+ this._bindSteps.push((effect) => {
41
+ effect.setColor3(this.getRemappedName(input.name), input.runtimeData.value);
42
+ });
43
+ break;
44
+ case ConnectionPointType.Color4:
45
+ this._bindSteps.push((effect) => {
46
+ effect.setDirectColor4(this.getRemappedName(input.name), input.runtimeData.value);
47
+ });
48
+ break;
49
+ case ConnectionPointType.Boolean:
50
+ this._bindSteps.push((effect) => {
51
+ effect.setBool(this.getRemappedName(input.name), input.runtimeData.value);
52
+ });
53
+ break;
54
+ case ConnectionPointType.Vector2:
55
+ switch (input.autoBind) {
56
+ case "outputResolution":
57
+ this._bindSteps.push((effect, width, height) => {
58
+ effect.setFloat2(this.getRemappedName(input.name), width, height);
59
+ });
60
+ break;
61
+ case "outputAspectRatio":
62
+ this._bindSteps.push((effect, width, height) => {
63
+ effect.setFloat2(this.getRemappedName(input.name), width / height, height / width);
64
+ });
65
+ break;
66
+ default:
67
+ this._bindSteps.push((effect) => {
68
+ effect.setVector2(this.getRemappedName(input.name), input.runtimeData.value);
69
+ });
70
+ }
71
+ break;
72
+ }
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Binds all the required data to the shader when rendering.
78
+ * @param effect - The effect to bind the data to
79
+ * @param width - defines the width of the output
80
+ * @param height - defines the height of the output
81
+ */
82
+ public override bind(effect: Effect, width: number, height: number): void {
83
+ for (let i = 0; i < this._bindSteps.length; i++) {
84
+ this._bindSteps[i]!(effect, width, height);
85
+ }
86
+ }
87
+ }
88
+
89
+ /**
90
+ * A block which loads a SerializedBlockDefinition for use in a SmartFilter.
91
+ */
92
+ export class CustomShaderBlock extends ShaderBlock {
93
+ /**
94
+ * Deserializes a CustomShaderBlock from a serialized block definition.
95
+ * @param smartFilter - The smart filter this block belongs to
96
+ * @param name - Defines the name of the block
97
+ * @param blockDefinition - The serialized block definition
98
+ * @returns The deserialized CustomShaderBlock instance
99
+ */
100
+ public static Create(smartFilter: SmartFilter, name: string, blockDefinition: SerializedShaderBlockDefinition): CustomShaderBlock {
101
+ // When a new version of SerializedBlockDefinition is created, this function should be updated to handle the new properties.
102
+
103
+ return new CustomShaderBlock(
104
+ smartFilter,
105
+ name,
106
+ blockDefinition.disableOptimization,
107
+ blockDefinition.blockType,
108
+ blockDefinition.namespace,
109
+ blockDefinition.inputConnectionPoints,
110
+ blockDefinition.shaderProgram
111
+ );
112
+ }
113
+
114
+ /**
115
+ * The class name of the block.
116
+ */
117
+ public static override ClassName = "CustomShaderBlock";
118
+
119
+ private readonly _shaderProgram: ShaderProgram;
120
+ private readonly _blockType: string;
121
+ private readonly _namespace: Nullable<string>;
122
+ private _autoBoundInputs: Nullable<SerializedInputConnectionPointV1[]> = null;
123
+
124
+ /**
125
+ * The type of the block - used when serializing / deserializing the block, and in the editor.
126
+ */
127
+ public override get blockType(): string {
128
+ return this._blockType;
129
+ }
130
+
131
+ /**
132
+ * The namespace of the block, which is used to reduce name collisions between blocks and also to group blocks in the editor UI.
133
+ * By convention, sub namespaces are separated by a period (e.g. "Babylon.Demo.Effects").
134
+ */
135
+ public override get namespace(): Nullable<string> {
136
+ return this._namespace;
137
+ }
138
+
139
+ /**
140
+ * Instantiates a new custom shader block.
141
+ * @param smartFilter - The smart filter this block belongs to
142
+ * @param name - The name of the block
143
+ * @param disableOptimization - If true, this optimizer will not attempt to optimize this block
144
+ * @param blockType - The type of the block
145
+ * @param namespace - The namespace of the block
146
+ * @param inputConnectionPoints - The input connection points of the
147
+ * @param shaderProgram - The shader program for the block
148
+ */
149
+ private constructor(
150
+ smartFilter: SmartFilter,
151
+ name: string,
152
+ disableOptimization: boolean,
153
+ blockType: string,
154
+ namespace: Nullable<string>,
155
+ inputConnectionPoints: SerializedInputConnectionPointV1[],
156
+ shaderProgram: ShaderProgram
157
+ ) {
158
+ super(smartFilter, name, disableOptimization);
159
+ this._blockType = blockType;
160
+ this._namespace = namespace;
161
+
162
+ for (const input of inputConnectionPoints) {
163
+ this._registerSerializedInputConnectionPointV1(input);
164
+ }
165
+
166
+ this._shaderProgram = shaderProgram;
167
+ }
168
+
169
+ /**
170
+ * Gets the shader program to use to render the block.
171
+ * @returns The shader program to use to render the block
172
+ */
173
+ public override getShaderProgram() {
174
+ return this._shaderProgram;
175
+ }
176
+
177
+ /**
178
+ * Checks a specific input connection point type to see if it has a default value, and registers the input
179
+ * connection point accordingly.
180
+ * @param connectionPoint - The input connection point to register
181
+ */
182
+ private _registerSerializedInputConnectionPointV1<U extends ConnectionPointType>(connectionPoint: SerializedInputConnectionPointV1<U>): void {
183
+ if (connectionPoint.autoBind) {
184
+ // Auto bound inputs are not registered as input connection points
185
+ if (this._autoBoundInputs === null) {
186
+ this._autoBoundInputs = [];
187
+ }
188
+ this._autoBoundInputs.push(connectionPoint);
189
+ } else {
190
+ // If not auto bound, register as an input connection point
191
+ const defaultValue = this._validateDefaultValue(connectionPoint.type, connectionPoint.name, connectionPoint.defaultValue);
192
+ if (defaultValue != null) {
193
+ this._registerOptionalInput(connectionPoint.name, connectionPoint.type, CreateStrongRef(defaultValue));
194
+ } else {
195
+ this._registerInput(connectionPoint.name, connectionPoint.type);
196
+ }
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Gets the shader binding for the custom shader block.
202
+ * @returns The shader binding for the custom shader block
203
+ */
204
+ public override getShaderBinding(): ShaderBinding {
205
+ const inputs = this.inputs;
206
+
207
+ const inputsToBind: AnyInputWithRuntimeData[] = inputs.map((input) => {
208
+ return {
209
+ name: input.name,
210
+ type: input.type,
211
+ runtimeData: this._confirmRuntimeDataSupplied(input),
212
+ autoBind: undefined,
213
+ };
214
+ });
215
+
216
+ if (this._autoBoundInputs) {
217
+ for (const autoBoundInput of this._autoBoundInputs) {
218
+ if (
219
+ (autoBoundInput.autoBind === "outputResolution" && autoBoundInput.type == ConnectionPointType.Vector2) ||
220
+ (autoBoundInput.autoBind === "outputAspectRatio" && autoBoundInput.type == ConnectionPointType.Vector2)
221
+ ) {
222
+ inputsToBind.push({
223
+ name: autoBoundInput.name,
224
+ type: autoBoundInput.type,
225
+ autoBind: autoBoundInput.autoBind,
226
+ });
227
+ } else {
228
+ throw new Error(`Auto bound input ${autoBoundInput.name} has an unsupported type or auto bind value`);
229
+ }
230
+ }
231
+ }
232
+
233
+ return new CustomShaderBlockBinding(inputsToBind);
234
+ }
235
+
236
+ /**
237
+ * Validates the default value of a connection point and returns it if valid.
238
+ * If the default value is not provided or is invalid, this returns null.
239
+ * @param connectionPointType - The type of the connection point
240
+ * @param connectionPointName - The name of the connection point
241
+ * @param defaultValue - The default value of the connection point
242
+ * @returns The default value, or null if no default value is provided or it was invalid
243
+ */
244
+ private _validateDefaultValue<U extends ConnectionPointType>(
245
+ connectionPointType: U,
246
+ connectionPointName: string,
247
+ defaultValue?: ConnectionPointValue<U>
248
+ ): Nullable<ConnectionPointValue<U>> {
249
+ if (defaultValue === undefined || defaultValue === null) {
250
+ return null;
251
+ }
252
+
253
+ // Validate the default value based on the connection point type
254
+ let returnValue: Nullable<ConnectionPointValue<U>> = null;
255
+ switch (connectionPointType) {
256
+ case ConnectionPointType.Float:
257
+ returnValue = typeof defaultValue === "number" ? defaultValue : null;
258
+ break;
259
+ case ConnectionPointType.Color3:
260
+ returnValue = typeof defaultValue === "object" && "r" in defaultValue && "g" in defaultValue && "b" in defaultValue ? defaultValue : null;
261
+ break;
262
+ case ConnectionPointType.Color4:
263
+ returnValue = typeof defaultValue === "object" && "r" in defaultValue && "g" in defaultValue && "b" in defaultValue && "a" in defaultValue ? defaultValue : null;
264
+ break;
265
+ case ConnectionPointType.Boolean:
266
+ returnValue = typeof defaultValue === "boolean" ? defaultValue : null;
267
+ break;
268
+ case ConnectionPointType.Vector2:
269
+ returnValue = typeof defaultValue === "object" && "x" in defaultValue && "y" in defaultValue ? defaultValue : null;
270
+ break;
271
+ default: {
272
+ Logger.Warn(`Default value supplied when unsupported. Block Type: "${this.blockType}" Connection Point: "${connectionPointName}"`);
273
+ return null;
274
+ }
275
+ }
276
+
277
+ if (returnValue === null) {
278
+ Logger.Warn(`Invalid default value. Block Type: "${this.blockType}" Connection Point: "${connectionPointName}"`);
279
+ }
280
+
281
+ return returnValue;
282
+ }
283
+ }
284
+
285
+ /**
286
+ * Represents an input with its runtime data, enforcing type safety.
287
+ */
288
+ type InputWithRuntimeData<U extends ConnectionPointType> = {
289
+ /**
290
+ * The name of the input connection point
291
+ */
292
+ name: string;
293
+
294
+ /**
295
+ * The type of the input connection point
296
+ */
297
+ type: U;
298
+
299
+ /**
300
+ * The runtime data for the input connection point
301
+ */
302
+ runtimeData: RuntimeData<U>;
303
+
304
+ /**
305
+ * Since this is an input connection point, it will not be auto bound
306
+ */
307
+ autoBind: undefined;
308
+ };
309
+
310
+ /**
311
+ * Represents an input which is auto-bound to the output resolution instead of an input connection point
312
+ */
313
+ type AutoBindOutputResolution = {
314
+ /**
315
+ * The name of the input
316
+ */
317
+ name: string;
318
+
319
+ /**
320
+ * The type of the input
321
+ */
322
+ type: ConnectionPointType.Vector2;
323
+
324
+ /**
325
+ * The auto bind value for the input connection point
326
+ */
327
+ autoBind: "outputResolution";
328
+ };
329
+
330
+ /**
331
+ * Represents an input which is auto-bound to the output's aspect ratio instead of an input connection point.
332
+ * The x value is the aspect ratio (width / height) and the y value is the inverse aspect ratio (height / width).
333
+ */
334
+ type AutoBindOutputAspectRatio = {
335
+ /**
336
+ * The name of the input
337
+ */
338
+ name: string;
339
+
340
+ /**
341
+ * The type of the input
342
+ */
343
+ type: ConnectionPointType.Vector2;
344
+
345
+ /**
346
+ * The auto bind value for the input connection point
347
+ */
348
+ autoBind: "outputAspectRatio";
349
+ };
350
+
351
+ /**
352
+ * All possible input types with runtime data.
353
+ */
354
+ type AnyInputWithRuntimeData =
355
+ | InputWithRuntimeData<ConnectionPointType.Boolean>
356
+ | InputWithRuntimeData<ConnectionPointType.Color3>
357
+ | InputWithRuntimeData<ConnectionPointType.Color4>
358
+ | InputWithRuntimeData<ConnectionPointType.Float>
359
+ | InputWithRuntimeData<ConnectionPointType.Texture>
360
+ | InputWithRuntimeData<ConnectionPointType.Vector2>
361
+ | AutoBindOutputResolution
362
+ | AutoBindOutputAspectRatio;
@@ -0,0 +1,91 @@
1
+ import type { SmartFilter } from "../smartFilter.js";
2
+ import type { ConnectionPoint } from "../connection/connectionPoint.js";
3
+
4
+ import { ConnectionPointType } from "../connection/connectionPointType.js";
5
+ import { CreateStrongRef } from "../runtime/strongRef.js";
6
+ import { ShaderBlock } from "./shaderBlock.js";
7
+ import { InjectAutoSampleDisableCode } from "../utils/shaderCodeUtils.js";
8
+
9
+ /**
10
+ * The interface that describes the disableable block.
11
+ */
12
+ export interface IDisableableBlock {
13
+ /**
14
+ * The disabled connection point of the block.
15
+ */
16
+ disabled: ConnectionPoint<ConnectionPointType.Boolean>;
17
+ }
18
+
19
+ /**
20
+ * The strategy to use for making a block disableable.
21
+ */
22
+ export enum BlockDisableStrategy {
23
+ /**
24
+ * The shader code is responsible for defining and consulting a uniform named disabled
25
+ * and no-oping (returning texture2D(mainInputTexture, vUV)) if the value is true.
26
+ */
27
+ Manual = 0,
28
+
29
+ /**
30
+ * The Smart Filter system will automatically add code to sample the mainInputTexture and return immediately if disabled,
31
+ * and otherwise use the value within the block's shader code. If you need to modify UVs before sampling the default input texture,
32
+ * you'll need to use the Manual strategy instead.
33
+ */
34
+ AutoSample = 1,
35
+ }
36
+
37
+ /**
38
+ * A ShaderBlock that can be disabled. The optimizer can optionally remove disabled blocks from the graph,
39
+ * or they can be controlled by the disabled connection point at runtime. If disabled, they pass the
40
+ * mainInputTexture through to the output connection point.
41
+ */
42
+ export abstract class DisableableShaderBlock extends ShaderBlock implements IDisableableBlock {
43
+ /**
44
+ * The disabled connection point of the block.
45
+ */
46
+ public readonly disabled = this._registerOptionalInput("disabled", ConnectionPointType.Boolean, CreateStrongRef(false));
47
+
48
+ /**
49
+ * The strategy to use for making this block disableable.
50
+ */
51
+ public readonly blockDisableStrategy: BlockDisableStrategy;
52
+
53
+ // The shader code is a static per block type. When an instance of a block is created, we may need to alter
54
+ // that code based on the block's disable strategy. We only want to do this once per block type, or we could
55
+ // incorrectly modify the shader code multiple times (once per block instance). Here we use a static boolean
56
+ // which will be per block type to track if we've already modified the shader code for this block type.
57
+ // This is more memory efficient than the alternative of making a copy of the shader code for each block instance
58
+ // and modifying each copy.
59
+ private static _HasModifiedShaderCode = false;
60
+ private get _hasModifiedShaderCode() {
61
+ return (this.constructor as typeof DisableableShaderBlock)._HasModifiedShaderCode;
62
+ }
63
+ private set _hasModifiedShaderCode(value: boolean) {
64
+ (this.constructor as typeof DisableableShaderBlock)._HasModifiedShaderCode = value;
65
+ }
66
+
67
+ /**
68
+ * Instantiates a new block.
69
+ * @param smartFilter - Defines the smart filter the block belongs to
70
+ * @param name - Defines the name of the block
71
+ * @param disableOptimization - Defines if the block should not be optimized (default: false)
72
+ * @param disableStrategy - Defines the strategy to use for making this block disableable (default: BlockDisableStrategy.AutoSample)
73
+ */
74
+ constructor(smartFilter: SmartFilter, name: string, disableOptimization = false, disableStrategy = BlockDisableStrategy.AutoSample) {
75
+ super(smartFilter, name, disableOptimization);
76
+ this.blockDisableStrategy = disableStrategy;
77
+
78
+ // If we haven't already modified the shader code for this block type, do so now
79
+ if (!this._hasModifiedShaderCode) {
80
+ this._hasModifiedShaderCode = true;
81
+
82
+ // Apply the disable strategy
83
+ const shaderProgram = this.getShaderProgram();
84
+ switch (this.blockDisableStrategy) {
85
+ case BlockDisableStrategy.AutoSample:
86
+ InjectAutoSampleDisableCode(shaderProgram);
87
+ break;
88
+ }
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,9 @@
1
+ export { BaseBlock } from "./baseBlock.js";
2
+ export { InputBlock, type InputBlockEditorData } from "./inputBlock.js";
3
+ export { type AnyInputBlock } from "./inputBlock.js";
4
+ export { ShaderBlock } from "./shaderBlock.js";
5
+ export { CustomShaderBlock } from "./customShaderBlock.js";
6
+ export { CustomAggregateBlock } from "./customAggregateBlock.js";
7
+ export { DisableableShaderBlock, BlockDisableStrategy } from "./disableableShaderBlock.js";
8
+ export { AggregateBlock } from "./aggregateBlock.js";
9
+ export { type IDisableableBlock } from "./disableableShaderBlock.js";
@@ -0,0 +1,72 @@
1
+ import { InputBlock } from "./inputBlock.js";
2
+ import type { SerializedInputBlockData } from "./inputBlock.serialization.types.js";
3
+ import { ConnectionPointType } from "../connection/connectionPointType.js";
4
+ import type { SmartFilter } from "../smartFilter.js";
5
+ import type { ISerializedBlockV1 } from "../serialization/v1/smartFilterSerialization.types.js";
6
+
7
+ /**
8
+ * V1 Input Block Deserializer
9
+ * @param smartFilter - The SmartFilter to deserialize the block into
10
+ * @param serializedBlock - The serialized block data
11
+ * @returns A deserialized InputBlock
12
+ */
13
+ export function InputBlockDeserializer(smartFilter: SmartFilter, serializedBlock: ISerializedBlockV1) {
14
+ const blockData = serializedBlock.data as SerializedInputBlockData;
15
+ let inputBlock;
16
+
17
+ switch (blockData.inputType) {
18
+ case ConnectionPointType.Boolean:
19
+ {
20
+ inputBlock = new InputBlock(smartFilter, serializedBlock.name, ConnectionPointType.Boolean, blockData.value);
21
+ }
22
+ break;
23
+ case ConnectionPointType.Float:
24
+ {
25
+ inputBlock = new InputBlock(smartFilter, serializedBlock.name, ConnectionPointType.Float, blockData.value);
26
+ inputBlock.editorData = {
27
+ animationType: blockData.animationType,
28
+ valueDeltaPerMs: blockData.valueDeltaPerMs,
29
+ min: blockData.min,
30
+ max: blockData.max,
31
+ };
32
+ }
33
+ break;
34
+ case ConnectionPointType.Texture:
35
+ {
36
+ // Create the input block
37
+ inputBlock = new InputBlock(smartFilter, serializedBlock.name, ConnectionPointType.Texture, null);
38
+
39
+ // If editor data was serialized, set it on the deserialized block
40
+ inputBlock.editorData = {
41
+ url: blockData.url,
42
+ urlTypeHint: blockData.urlTypeHint,
43
+ anisotropicFilteringLevel: blockData.anisotropicFilteringLevel,
44
+ flipY: blockData.flipY,
45
+ forcedExtension: blockData.forcedExtension,
46
+ };
47
+ }
48
+ break;
49
+ case ConnectionPointType.Color3:
50
+ {
51
+ inputBlock = new InputBlock(smartFilter, serializedBlock.name, ConnectionPointType.Color3, blockData.value);
52
+ }
53
+ break;
54
+ case ConnectionPointType.Color4:
55
+ {
56
+ inputBlock = new InputBlock(smartFilter, serializedBlock.name, ConnectionPointType.Color4, blockData.value);
57
+ }
58
+ break;
59
+ case ConnectionPointType.Vector2:
60
+ {
61
+ inputBlock = new InputBlock(smartFilter, serializedBlock.name, ConnectionPointType.Vector2, blockData.value);
62
+ }
63
+ break;
64
+ }
65
+ if (inputBlock) {
66
+ inputBlock.appMetadata = blockData.appMetadata;
67
+
68
+ return inputBlock;
69
+ }
70
+
71
+ throw new Error("Could not deserialize input block, unknown input type");
72
+ }
@@ -0,0 +1,126 @@
1
+ import type { Nullable } from "core/types.js";
2
+ import type { ConnectionPointType } from "../connection/connectionPointType.js";
3
+ import type { IColor3Like, IColor4Like, IVector2Like } from "core/Maths/math.like.js";
4
+
5
+ /**
6
+ * Data that all serialized InputBlocks share
7
+ */
8
+ export type CommonInputBlockData = {
9
+ /**
10
+ * Metadata the hosting app wants to track for this input. For example, a hint for what data to
11
+ * assign to this input, or hints about how to draw dynamic UI to allow users to control this value.
12
+ */
13
+ appMetadata: unknown;
14
+ };
15
+
16
+ /**
17
+ * The data for an InputBlock for ConnectionPointType.Texture inputs
18
+ */
19
+ export type TextureInputBlockData = CommonInputBlockData & {
20
+ /** The type of the input block */
21
+ inputType: ConnectionPointType.Texture;
22
+
23
+ /** The URL, if available, of the texture */
24
+ url: Nullable<string>;
25
+
26
+ /**
27
+ * If supplied, gives a hint as to which type of texture the URL points to.
28
+ * Default is assumed to be "image"
29
+ */
30
+ urlTypeHint: Nullable<"image" | "video">;
31
+
32
+ /**
33
+ * Defines the anisotropic level to use, or default if null
34
+ */
35
+ anisotropicFilteringLevel: Nullable<number>;
36
+
37
+ /**
38
+ * Indicates if the Y axis should be flipped, or default if null
39
+ */
40
+ flipY: Nullable<boolean>;
41
+
42
+ /**
43
+ * The file extension to use, or default if null.
44
+ */
45
+ forcedExtension: Nullable<string>;
46
+ };
47
+
48
+ /**
49
+ * The data for an InputBlock for ConnectionPointType.Boolean inputs
50
+ */
51
+ export type BooleanInputBlockData = CommonInputBlockData & {
52
+ /** The type of the input block */
53
+ inputType: ConnectionPointType.Boolean;
54
+
55
+ /** The value of the input block */
56
+ value: boolean;
57
+ };
58
+
59
+ /**
60
+ * The data for an InputBlock for ConnectionPointType.Float inputs
61
+ */
62
+ export type FloatInputBlockData = CommonInputBlockData & {
63
+ /** The type of the input block */
64
+ inputType: ConnectionPointType.Float;
65
+
66
+ /** The value of the input block */
67
+ value: number;
68
+
69
+ /**
70
+ * If supplied, how this should be animated by the editor. Will not affect runtime behavior.
71
+ */
72
+ animationType: Nullable<"time">;
73
+
74
+ /**
75
+ * If supplied, the amount to change the value per millisecond when animating.
76
+ */
77
+ valueDeltaPerMs: Nullable<number>;
78
+
79
+ /**
80
+ * The minimum value of the float, used for slider control.
81
+ */
82
+ min: Nullable<number>;
83
+
84
+ /**
85
+ * The maximum value of the float, used for slider control.
86
+ */
87
+ max: Nullable<number>;
88
+ };
89
+
90
+ /**
91
+ * The data for an InputBlock for ConnectionPointType.Color3 inputs
92
+ */
93
+ export type Color3InputBlockData = CommonInputBlockData & {
94
+ /** The type of the input block */
95
+ inputType: ConnectionPointType.Color3;
96
+
97
+ /** The value of the input block */
98
+ value: IColor3Like;
99
+ };
100
+
101
+ /**
102
+ * The data for an InputBlock for ConnectionPointType.Color4 inputs
103
+ */
104
+ export type Color4InputBlockData = CommonInputBlockData & {
105
+ /** The type of the input block */
106
+ inputType: ConnectionPointType.Color4;
107
+
108
+ /** The value of the input block */
109
+ value: IColor4Like;
110
+ };
111
+
112
+ /**
113
+ * The data for an InputBlock for ConnectionPointType.Vector2 inputs
114
+ */
115
+ export type Vector2InputBlockData = CommonInputBlockData & {
116
+ /** The type of the input block */
117
+ inputType: ConnectionPointType.Vector2;
118
+
119
+ /** The value of the input block */
120
+ value: IVector2Like;
121
+ };
122
+
123
+ /**
124
+ * Type union of all possible InputBlock data types
125
+ */
126
+ export type SerializedInputBlockData = TextureInputBlockData | BooleanInputBlockData | FloatInputBlockData | Color3InputBlockData | Color4InputBlockData | Vector2InputBlockData;