@babylonjs/smart-filters 0.1.0-alpha → 0.3.0-alpha
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/dist/blocks/baseBlock.d.ts +1 -1
- package/dist/blocks/baseBlock.d.ts.map +1 -1
- package/dist/blocks/baseBlock.js +1 -1
- package/dist/blocks/baseBlock.js.map +1 -1
- package/dist/blocks/copyBlock.d.ts +5 -7
- package/dist/blocks/copyBlock.d.ts.map +1 -1
- package/dist/blocks/copyBlock.js +4 -24
- package/dist/blocks/copyBlock.js.map +1 -1
- package/dist/blocks/copyBlock.shader.d.ts +13 -0
- package/dist/blocks/copyBlock.shader.d.ts.map +1 -0
- package/dist/blocks/copyBlock.shader.js +31 -0
- package/dist/blocks/copyBlock.shader.js.map +1 -0
- package/dist/blocks/inputBlock.d.ts +15 -5
- package/dist/blocks/inputBlock.d.ts.map +1 -1
- package/dist/blocks/inputBlock.deserializer.d.ts +14 -0
- package/dist/blocks/inputBlock.deserializer.d.ts.map +1 -0
- package/dist/blocks/inputBlock.deserializer.js +23 -0
- package/dist/blocks/inputBlock.deserializer.js.map +1 -0
- package/dist/blocks/inputBlock.js +12 -6
- package/dist/blocks/inputBlock.js.map +1 -1
- package/dist/blocks/inputBlock.serialization.types.d.ts +62 -0
- package/dist/blocks/inputBlock.serialization.types.d.ts.map +1 -0
- package/dist/blocks/inputBlock.serialization.types.js +2 -0
- package/dist/blocks/inputBlock.serialization.types.js.map +1 -0
- package/dist/blocks/inputBlock.serializer.d.ts +6 -0
- package/dist/blocks/inputBlock.serializer.d.ts.map +1 -0
- package/dist/blocks/inputBlock.serializer.js +110 -0
- package/dist/blocks/inputBlock.serializer.js.map +1 -0
- package/dist/connection/connectionPointType.d.ts +6 -3
- package/dist/connection/connectionPointType.d.ts.map +1 -1
- package/dist/connection/connectionPointType.js +2 -0
- package/dist/connection/connectionPointType.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/optimization/optimizedShaderBlock.d.ts +3 -3
- package/dist/optimization/optimizedShaderBlock.d.ts.map +1 -1
- package/dist/optimization/optimizedShaderBlock.js.map +1 -1
- package/dist/runtime/renderTargetGenerator.d.ts.map +1 -1
- package/dist/runtime/renderTargetGenerator.js +3 -1
- package/dist/runtime/renderTargetGenerator.js.map +1 -1
- package/dist/serialization/index.d.ts +5 -0
- package/dist/serialization/index.d.ts.map +1 -0
- package/dist/serialization/index.js +5 -0
- package/dist/serialization/index.js.map +1 -0
- package/dist/serialization/serializedSmartFilter.d.ts +6 -0
- package/dist/serialization/serializedSmartFilter.d.ts.map +1 -0
- package/dist/serialization/serializedSmartFilter.js +2 -0
- package/dist/serialization/serializedSmartFilter.js.map +1 -0
- package/dist/serialization/smartFilterDeserializer.d.ts +25 -0
- package/dist/serialization/smartFilterDeserializer.d.ts.map +1 -0
- package/dist/serialization/smartFilterDeserializer.js +94 -0
- package/dist/serialization/smartFilterDeserializer.js.map +1 -0
- package/dist/serialization/smartFilterSerializer.d.ts +23 -0
- package/dist/serialization/smartFilterSerializer.d.ts.map +1 -0
- package/dist/serialization/smartFilterSerializer.js +91 -0
- package/dist/serialization/smartFilterSerializer.js.map +1 -0
- package/dist/serialization/v1/defaultBlockSerializer.d.ts +9 -0
- package/dist/serialization/v1/defaultBlockSerializer.d.ts.map +1 -0
- package/dist/serialization/v1/defaultBlockSerializer.js +16 -0
- package/dist/serialization/v1/defaultBlockSerializer.js.map +1 -0
- package/dist/serialization/v1/index.d.ts +3 -0
- package/dist/serialization/v1/index.d.ts.map +1 -0
- package/dist/serialization/v1/index.js +3 -0
- package/dist/serialization/v1/index.js.map +1 -0
- package/dist/serialization/v1/serialization.types.d.ts +83 -0
- package/dist/serialization/v1/serialization.types.d.ts.map +1 -0
- package/dist/serialization/v1/serialization.types.js +2 -0
- package/dist/serialization/v1/serialization.types.js.map +1 -0
- package/dist/smartFilter.d.ts +2 -2
- package/dist/smartFilter.d.ts.map +1 -1
- package/dist/smartFilter.js +0 -1
- package/dist/smartFilter.js.map +1 -1
- package/dist/utils/buildTools/shaderConverter.d.ts +2 -0
- package/dist/utils/buildTools/shaderConverter.d.ts.map +1 -0
- package/dist/utils/buildTools/shaderConverter.js +271 -0
- package/dist/utils/buildTools/shaderConverter.js.map +1 -0
- package/dist/utils/textureLoaders.d.ts +2 -1
- package/dist/utils/textureLoaders.d.ts.map +1 -1
- package/dist/utils/textureLoaders.js +3 -2
- package/dist/utils/textureLoaders.js.map +1 -1
- package/dist/utils/uniqueIdGenerator.d.ts +19 -0
- package/dist/utils/uniqueIdGenerator.d.ts.map +1 -0
- package/dist/utils/uniqueIdGenerator.js +27 -0
- package/dist/utils/uniqueIdGenerator.js.map +1 -0
- package/package.json +11 -5
- package/readme.md +12 -0
- package/src/blocks/baseBlock.ts +3 -4
- package/src/blocks/copyBlock.fragment.glsl +5 -0
- package/src/blocks/copyBlock.shader.ts +33 -0
- package/src/blocks/copyBlock.ts +7 -33
- package/src/blocks/inputBlock.deserializer.ts +38 -0
- package/src/blocks/inputBlock.serialization.types.ts +80 -0
- package/src/blocks/inputBlock.serializer.ts +127 -0
- package/src/blocks/inputBlock.ts +18 -7
- package/src/connection/connectionPointType.ts +6 -2
- package/src/index.ts +1 -0
- package/src/optimization/optimizedShaderBlock.ts +6 -5
- package/src/runtime/renderTargetGenerator.ts +5 -1
- package/src/serialization/index.ts +4 -0
- package/src/serialization/serializedSmartFilter.ts +6 -0
- package/src/serialization/smartFilterDeserializer.ts +127 -0
- package/src/serialization/smartFilterSerializer.ts +113 -0
- package/src/serialization/v1/defaultBlockSerializer.ts +18 -0
- package/src/serialization/v1/index.ts +2 -0
- package/src/serialization/v1/serialization.types.ts +108 -0
- package/src/smartFilter.ts +2 -2
- package/src/utils/buildTools/shaderConverter.ts +388 -0
- package/src/utils/textureLoaders.ts +16 -2
- package/src/utils/uniqueIdGenerator.ts +28 -0
|
@@ -0,0 +1,38 @@
|
|
|
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/serialization.types.js";
|
|
6
|
+
import { createImageTexture } from "../utils/textureLoaders.js";
|
|
7
|
+
import type { ThinEngine } from "@babylonjs/core/Engines/thinEngine.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* V1 Input Block Deserializer
|
|
11
|
+
* @param smartFilter - The SmartFilter to deserialize the block into
|
|
12
|
+
* @param serializedBlock - The serialized block data
|
|
13
|
+
* @param engine - The ThinEngine to use for loading textures
|
|
14
|
+
* @returns A deserialized InputBlock
|
|
15
|
+
*/
|
|
16
|
+
export function inputBlockDeserializer(
|
|
17
|
+
smartFilter: SmartFilter,
|
|
18
|
+
serializedBlock: ISerializedBlockV1,
|
|
19
|
+
engine: ThinEngine
|
|
20
|
+
) {
|
|
21
|
+
const blockData = serializedBlock.data as SerializedInputBlockData;
|
|
22
|
+
|
|
23
|
+
switch (blockData.inputType) {
|
|
24
|
+
case ConnectionPointType.Boolean:
|
|
25
|
+
return new InputBlock(smartFilter, serializedBlock.name, ConnectionPointType.Boolean, blockData.value);
|
|
26
|
+
case ConnectionPointType.Float:
|
|
27
|
+
return new InputBlock(smartFilter, serializedBlock.name, ConnectionPointType.Float, blockData.value);
|
|
28
|
+
case ConnectionPointType.Texture:
|
|
29
|
+
return new InputBlock(
|
|
30
|
+
smartFilter,
|
|
31
|
+
serializedBlock.name,
|
|
32
|
+
ConnectionPointType.Texture,
|
|
33
|
+
blockData.url !== null ? createImageTexture(engine, blockData.url) : null
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
throw new Error("Could not deserialize input block, unknown input type");
|
|
38
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { Nullable } from "@babylonjs/core";
|
|
2
|
+
import type { ConnectionPointType } from "../connection/connectionPointType.js";
|
|
3
|
+
import type { IColor3Like, IColor4Like, IVector2Like } from "@babylonjs/core/Maths/math.like.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The data for an InputBlock for ConnectionPointType.Texture inputs
|
|
7
|
+
*/
|
|
8
|
+
export type TextureInputBlockData = {
|
|
9
|
+
/** The type of the input block */
|
|
10
|
+
inputType: ConnectionPointType.Texture;
|
|
11
|
+
|
|
12
|
+
/** The URL, if available, of the texture */
|
|
13
|
+
url: Nullable<string>;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The data for an InputBlock for ConnectionPointType.Boolean inputs
|
|
18
|
+
*/
|
|
19
|
+
export type BooleanInputBlockData = {
|
|
20
|
+
/** The type of the input block */
|
|
21
|
+
inputType: ConnectionPointType.Boolean;
|
|
22
|
+
|
|
23
|
+
/** The value of the input block */
|
|
24
|
+
value: boolean;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The data for an InputBlock for ConnectionPointType.Float inputs
|
|
29
|
+
*/
|
|
30
|
+
export type FloatInputBlockData = {
|
|
31
|
+
/** The type of the input block */
|
|
32
|
+
inputType: ConnectionPointType.Float;
|
|
33
|
+
|
|
34
|
+
/** The value of the input block */
|
|
35
|
+
value: number;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The data for an InputBlock for ConnectionPointType.Color3 inputs
|
|
40
|
+
*/
|
|
41
|
+
export type Color3InputBlockData = {
|
|
42
|
+
/** The type of the input block */
|
|
43
|
+
inputType: ConnectionPointType.Color3;
|
|
44
|
+
|
|
45
|
+
/** The value of the input block */
|
|
46
|
+
value: IColor3Like;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The data for an InputBlock for ConnectionPointType.Color4 inputs
|
|
51
|
+
*/
|
|
52
|
+
export type Color4InputBlockData = {
|
|
53
|
+
/** The type of the input block */
|
|
54
|
+
inputType: ConnectionPointType.Color4;
|
|
55
|
+
|
|
56
|
+
/** The value of the input block */
|
|
57
|
+
value: IColor4Like;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The data for an InputBlock for ConnectionPointType.Vector2 inputs
|
|
62
|
+
*/
|
|
63
|
+
export type Vector2InputBlockData = {
|
|
64
|
+
/** The type of the input block */
|
|
65
|
+
inputType: ConnectionPointType.Vector2;
|
|
66
|
+
|
|
67
|
+
/** The value of the input block */
|
|
68
|
+
value: IVector2Like;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Type union of all possible InputBlock data types
|
|
73
|
+
*/
|
|
74
|
+
export type SerializedInputBlockData =
|
|
75
|
+
| TextureInputBlockData
|
|
76
|
+
| BooleanInputBlockData
|
|
77
|
+
| FloatInputBlockData
|
|
78
|
+
| Color3InputBlockData
|
|
79
|
+
| Color4InputBlockData
|
|
80
|
+
| Vector2InputBlockData;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { InputBlockBase, type InputBlock } from "./inputBlock.js";
|
|
2
|
+
import type { BaseBlock } from "./baseBlock.js";
|
|
3
|
+
import { ConnectionPointType } from "../connection/connectionPointType.js";
|
|
4
|
+
import type {
|
|
5
|
+
BooleanInputBlockData,
|
|
6
|
+
Color3InputBlockData,
|
|
7
|
+
Color4InputBlockData,
|
|
8
|
+
FloatInputBlockData,
|
|
9
|
+
SerializedInputBlockData,
|
|
10
|
+
TextureInputBlockData,
|
|
11
|
+
Vector2InputBlockData,
|
|
12
|
+
} from "./inputBlock.serialization.types";
|
|
13
|
+
import type { IBlockSerializerV1 } from "../serialization/v1/serialization.types";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Determines which generic type of InputBlock we are trying to serialize and calls the appropriate function
|
|
17
|
+
* to serialize the specifics for that type of InputBlock
|
|
18
|
+
* @param inputBlock - The InputBlock to serialize
|
|
19
|
+
* @returns Serialized data for the InputBlock
|
|
20
|
+
*/
|
|
21
|
+
function serializeInputBlockData(inputBlock: InputBlockBase): SerializedInputBlockData {
|
|
22
|
+
switch (inputBlock.type) {
|
|
23
|
+
case ConnectionPointType.Texture:
|
|
24
|
+
return serializeTextureInputBlock(inputBlock as InputBlock<ConnectionPointType.Texture>);
|
|
25
|
+
case ConnectionPointType.Boolean:
|
|
26
|
+
return serializeBooleanInputBlock(inputBlock as InputBlock<ConnectionPointType.Boolean>);
|
|
27
|
+
case ConnectionPointType.Float:
|
|
28
|
+
return serializeFloatInputBlock(inputBlock as InputBlock<ConnectionPointType.Float>);
|
|
29
|
+
case ConnectionPointType.Color3:
|
|
30
|
+
return serializeColor3InputBlock(inputBlock as InputBlock<ConnectionPointType.Color3>);
|
|
31
|
+
case ConnectionPointType.Color4:
|
|
32
|
+
return serializeColor4InputBlock(inputBlock as InputBlock<ConnectionPointType.Color4>);
|
|
33
|
+
case ConnectionPointType.Vector2:
|
|
34
|
+
return serializeVector2InputBlock(inputBlock as InputBlock<ConnectionPointType.Vector2>);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Generates the serialized data for a Texture InputBlock
|
|
40
|
+
* @param inputBlock - The Texture InputBlock to serialize
|
|
41
|
+
* @returns The serialized data for the InputBlock
|
|
42
|
+
*/
|
|
43
|
+
function serializeTextureInputBlock(inputBlock: InputBlock<ConnectionPointType.Texture>): TextureInputBlockData {
|
|
44
|
+
return {
|
|
45
|
+
inputType: ConnectionPointType.Texture,
|
|
46
|
+
url: inputBlock.runtimeValue.value?.getInternalTexture()?.url || null,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Generates the serialized data for a Boolean InputBlock
|
|
52
|
+
* @param inputBlock - The Boolean InputBlock to serialize
|
|
53
|
+
* @returns The serialized data for the InputBlock
|
|
54
|
+
*/
|
|
55
|
+
function serializeBooleanInputBlock(inputBlock: InputBlock<ConnectionPointType.Boolean>): BooleanInputBlockData {
|
|
56
|
+
return {
|
|
57
|
+
inputType: ConnectionPointType.Boolean,
|
|
58
|
+
value: inputBlock.runtimeValue.value,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Generates the serialized data for a Float InputBlock
|
|
64
|
+
* @param inputBlock - The Float InputBlock to serialize
|
|
65
|
+
* @returns The serialized data for the InputBlock
|
|
66
|
+
*/
|
|
67
|
+
function serializeFloatInputBlock(inputBlock: InputBlock<ConnectionPointType.Float>): FloatInputBlockData {
|
|
68
|
+
return {
|
|
69
|
+
inputType: ConnectionPointType.Float,
|
|
70
|
+
value: inputBlock.runtimeValue.value,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Generates the serialized data for a Color3 InputBlock
|
|
76
|
+
* @param inputBlock - The Color3 InputBlock to serialize
|
|
77
|
+
* @returns The serialized data for the InputBlock
|
|
78
|
+
*/
|
|
79
|
+
function serializeColor3InputBlock(inputBlock: InputBlock<ConnectionPointType.Color3>): Color3InputBlockData {
|
|
80
|
+
return {
|
|
81
|
+
inputType: ConnectionPointType.Color3,
|
|
82
|
+
value: inputBlock.runtimeValue.value,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Generates the serialized data for a Color4 InputBlock
|
|
88
|
+
* @param inputBlock - The Color4 InputBlock to serialize
|
|
89
|
+
* @returns The serialized data for the InputBlock
|
|
90
|
+
*/
|
|
91
|
+
function serializeColor4InputBlock(inputBlock: InputBlock<ConnectionPointType.Color4>): Color4InputBlockData {
|
|
92
|
+
return {
|
|
93
|
+
inputType: ConnectionPointType.Color4,
|
|
94
|
+
value: inputBlock.runtimeValue.value,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Generates the serialized data for a Vector2 InputBlock
|
|
100
|
+
* @param inputBlock - The Vector2 InputBlock to serialize
|
|
101
|
+
* @returns The serialized data for the InputBlock
|
|
102
|
+
*/
|
|
103
|
+
function serializeVector2InputBlock(inputBlock: InputBlock<ConnectionPointType.Vector2>): Vector2InputBlockData {
|
|
104
|
+
return {
|
|
105
|
+
inputType: ConnectionPointType.Vector2,
|
|
106
|
+
value: inputBlock.runtimeValue.value,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The V1 serializer for an InputBlock
|
|
112
|
+
*/
|
|
113
|
+
export const inputBlockSerializer: IBlockSerializerV1 = {
|
|
114
|
+
className: InputBlockBase.ClassName,
|
|
115
|
+
serialize: (block: BaseBlock) => {
|
|
116
|
+
if (block.getClassName() !== InputBlockBase.ClassName) {
|
|
117
|
+
throw new Error("Was asked to serialize an unrecognized block type");
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
name: block.name,
|
|
121
|
+
uniqueId: block.uniqueId,
|
|
122
|
+
className: InputBlockBase.ClassName,
|
|
123
|
+
comments: block.comments,
|
|
124
|
+
data: serializeInputBlockData(block as unknown as InputBlockBase),
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
};
|
package/src/blocks/inputBlock.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { ConnectionPointType } from "../connection/connectionPointType.js";
|
|
|
15
15
|
function isRuntimeData<U extends ConnectionPointType>(
|
|
16
16
|
value: ConnectionPointValue<U> | RuntimeData<U>
|
|
17
17
|
): value is RuntimeData<U> {
|
|
18
|
-
return (value as RuntimeData<ConnectionPointType>).value !== undefined;
|
|
18
|
+
return value && (value as RuntimeData<ConnectionPointType>).value !== undefined;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -37,18 +37,29 @@ export function isDisableableBlock(block: BaseBlock): block is DisableableBlock
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
|
-
* This
|
|
41
|
-
*
|
|
42
|
-
* This is used to provide a way to connect the graph to the outside world.
|
|
43
|
-
*
|
|
44
|
-
* The value is dynamically set by the user.
|
|
40
|
+
* This base class exists to provide a type that the serializer can use to represent
|
|
41
|
+
* any InputBlock without knowing the exact type it is.
|
|
45
42
|
*/
|
|
46
|
-
export class
|
|
43
|
+
export abstract class InputBlockBase extends BaseBlock {
|
|
47
44
|
/**
|
|
48
45
|
* The class name of the block.
|
|
49
46
|
*/
|
|
50
47
|
public static override ClassName = "InputBlock";
|
|
51
48
|
|
|
49
|
+
/**
|
|
50
|
+
* The type of the input.
|
|
51
|
+
*/
|
|
52
|
+
public abstract readonly type: ConnectionPointType;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* This represents any inputs used in the graph.
|
|
57
|
+
*
|
|
58
|
+
* This is used to provide a way to connect the graph to the outside world.
|
|
59
|
+
*
|
|
60
|
+
* The value is dynamically set by the user.
|
|
61
|
+
*/
|
|
62
|
+
export class InputBlock<U extends ConnectionPointType> extends InputBlockBase {
|
|
52
63
|
/**
|
|
53
64
|
* The output connection point of the block.
|
|
54
65
|
*/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ThinTexture } from "@babylonjs/core/Materials/Textures/thinTexture";
|
|
2
|
-
import type { IColor3Like, IColor4Like } from "@babylonjs/core/Maths/math.like";
|
|
2
|
+
import type { IColor3Like, IColor4Like, IVector2Like } from "@babylonjs/core/Maths/math.like";
|
|
3
|
+
import type { Nullable } from "@babylonjs/core/types";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Defines the type of a connection point.
|
|
@@ -15,6 +16,8 @@ export enum ConnectionPointType {
|
|
|
15
16
|
Color4 = 4,
|
|
16
17
|
/** Boolean */
|
|
17
18
|
Boolean = 5,
|
|
19
|
+
/** Vector2 */
|
|
20
|
+
Vector2 = 6,
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
/**
|
|
@@ -23,8 +26,9 @@ export enum ConnectionPointType {
|
|
|
23
26
|
// prettier-ignore
|
|
24
27
|
export type ConnectionPointValue<T extends ConnectionPointType = ConnectionPointType> =
|
|
25
28
|
T extends ConnectionPointType.Float ? number :
|
|
26
|
-
T extends ConnectionPointType.Texture ? ThinTexture :
|
|
29
|
+
T extends ConnectionPointType.Texture ? Nullable<ThinTexture> :
|
|
27
30
|
T extends ConnectionPointType.Color3 ? IColor3Like :
|
|
28
31
|
T extends ConnectionPointType.Color4 ? IColor4Like :
|
|
29
32
|
T extends ConnectionPointType.Boolean ? boolean :
|
|
33
|
+
T extends ConnectionPointType.Vector2 ? IVector2Like :
|
|
30
34
|
never;
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type { Effect } from "@babylonjs/core/Materials/effect";
|
|
2
2
|
import type { Nullable } from "@babylonjs/core/types";
|
|
3
|
-
import type { ThinTexture } from "@babylonjs/core/Materials/Textures/thinTexture";
|
|
4
3
|
|
|
5
4
|
import type { SmartFilter } from "../smartFilter";
|
|
6
5
|
import type { ShaderProgram } from "../utils/shaderCodeUtils";
|
|
7
|
-
import type { StrongRef } from "../runtime/strongRef";
|
|
8
6
|
import type { RuntimeData } from "../connection/connectionPoint";
|
|
9
7
|
import { ShaderBlock } from "../blocks/shaderBlock.js";
|
|
10
8
|
import { Binding } from "../runtime/shaderRuntime.js";
|
|
@@ -16,14 +14,17 @@ import { ConnectionPointType } from "../connection/connectionPointType.js";
|
|
|
16
14
|
*/
|
|
17
15
|
export class OptimizedShaderBinding extends Binding {
|
|
18
16
|
private _shaderBindings: Binding[];
|
|
19
|
-
private _inputTextures: { [name: string]:
|
|
17
|
+
private _inputTextures: { [name: string]: RuntimeData<ConnectionPointType.Texture> };
|
|
20
18
|
|
|
21
19
|
/**
|
|
22
20
|
* Creates a new shader binding instance for the OptimizedShader block.
|
|
23
21
|
* @param shaderBindings - The list of shader bindings to process
|
|
24
22
|
* @param inputTextures - The list of input textures to bind
|
|
25
23
|
*/
|
|
26
|
-
constructor(
|
|
24
|
+
constructor(
|
|
25
|
+
shaderBindings: Binding[],
|
|
26
|
+
inputTextures: { [name: string]: RuntimeData<ConnectionPointType.Texture> }
|
|
27
|
+
) {
|
|
27
28
|
super();
|
|
28
29
|
|
|
29
30
|
this._shaderBindings = shaderBindings;
|
|
@@ -56,7 +57,7 @@ export class OptimizedShaderBinding extends Binding {
|
|
|
56
57
|
*/
|
|
57
58
|
export class OptimizedShaderBlock extends ShaderBlock {
|
|
58
59
|
private _shaderBindings: Nullable<Binding[]>;
|
|
59
|
-
private _inputTextures: { [name: string]:
|
|
60
|
+
private _inputTextures: { [name: string]: RuntimeData<ConnectionPointType.Texture> } = {};
|
|
60
61
|
private _shaderProgram: ShaderProgram;
|
|
61
62
|
|
|
62
63
|
/**
|
|
@@ -93,7 +93,11 @@ export class RenderTargetGenerator {
|
|
|
93
93
|
continue;
|
|
94
94
|
}
|
|
95
95
|
const connectedBlock = input.connectedTo.ownerBlock;
|
|
96
|
-
if (
|
|
96
|
+
if (
|
|
97
|
+
connectedBlock instanceof ShaderBlock &&
|
|
98
|
+
connectedBlock.output.runtimeData &&
|
|
99
|
+
connectedBlock.output.runtimeData.value
|
|
100
|
+
) {
|
|
97
101
|
this._releaseTexture(connectedBlock.output.runtimeData.value, connectedBlock.textureRatio);
|
|
98
102
|
}
|
|
99
103
|
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { BaseBlock } from "../blocks/baseBlock";
|
|
2
|
+
import type { SerializedSmartFilter } from "./serializedSmartFilter.js";
|
|
3
|
+
import { SmartFilter } from "../smartFilter.js";
|
|
4
|
+
import { inputBlockDeserializer } from "../blocks/inputBlock.deserializer.js";
|
|
5
|
+
import { OutputBlock } from "../blocks/outputBlock.js";
|
|
6
|
+
import type { ThinEngine } from "@babylonjs/core/Engines/thinEngine";
|
|
7
|
+
import { InputBlock } from "../blocks/inputBlock.js";
|
|
8
|
+
import type {
|
|
9
|
+
DeserializeBlockV1,
|
|
10
|
+
ISerializedBlockV1,
|
|
11
|
+
ISerializedConnectionV1,
|
|
12
|
+
SerializedSmartFilterV1,
|
|
13
|
+
} from "./v1/serialization.types";
|
|
14
|
+
import { UniqueIdGenerator } from "../utils/uniqueIdGenerator.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Deserializes serialized SmartFilters. The caller passes in a map of block deserializers it wants to use,
|
|
18
|
+
* which allows the caller to provide custom deserializers for blocks beyond the core blocks.
|
|
19
|
+
* The deserializer supports versioned serialized SmartFilters.
|
|
20
|
+
*/
|
|
21
|
+
export class SmartFilterDeserializer {
|
|
22
|
+
private readonly _blockDeserializersV1: Map<string, DeserializeBlockV1> = new Map();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Creates a new SmartFilterDeserializer
|
|
26
|
+
* @param blockDeserializers - The map of block serializers to use, beyond those for the core blocks
|
|
27
|
+
*/
|
|
28
|
+
public constructor(blockDeserializers: Map<string, DeserializeBlockV1>) {
|
|
29
|
+
this._blockDeserializersV1 = blockDeserializers;
|
|
30
|
+
|
|
31
|
+
// Add in the core block deserializers - they are not delay loaded, so they are wrapped in Promise.resolve()
|
|
32
|
+
this._blockDeserializersV1.set(
|
|
33
|
+
InputBlock.ClassName,
|
|
34
|
+
(smartFilter: SmartFilter, serializedBlock: ISerializedBlockV1, engine: ThinEngine) =>
|
|
35
|
+
Promise.resolve(inputBlockDeserializer(smartFilter, serializedBlock, engine))
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Deserializes a SmartFilter from a JSON object - can be safely called multiple times and has no side effects within the class.
|
|
41
|
+
* @param engine - The ThinEngine to pass to the new SmartFilter
|
|
42
|
+
* @param smartFilterJson - The JSON object to deserialize
|
|
43
|
+
* @returns A promise that resolves to the deserialized SmartFilter
|
|
44
|
+
*/
|
|
45
|
+
public async deserialize(engine: ThinEngine, smartFilterJson: any): Promise<SmartFilter> {
|
|
46
|
+
const serializedSmartFilter: SerializedSmartFilter = smartFilterJson;
|
|
47
|
+
switch (serializedSmartFilter.version) {
|
|
48
|
+
case 1:
|
|
49
|
+
return await this._deserializeV1(engine, serializedSmartFilter);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private async _deserializeV1(
|
|
54
|
+
engine: ThinEngine,
|
|
55
|
+
serializedSmartFilter: SerializedSmartFilterV1
|
|
56
|
+
): Promise<SmartFilter> {
|
|
57
|
+
const smartFilter = new SmartFilter(serializedSmartFilter.name);
|
|
58
|
+
const blockMap = new Map<string, BaseBlock>();
|
|
59
|
+
|
|
60
|
+
// Deserialize the SmartFilter level data
|
|
61
|
+
smartFilter.comments = serializedSmartFilter.comments;
|
|
62
|
+
smartFilter.editorData = serializedSmartFilter.editorData;
|
|
63
|
+
|
|
64
|
+
// Deserialize the blocks
|
|
65
|
+
const blockDeserializationWork: Promise<void>[] = [];
|
|
66
|
+
serializedSmartFilter.blocks.forEach((serializedBlock: ISerializedBlockV1) => {
|
|
67
|
+
if (serializedBlock.className === OutputBlock.ClassName) {
|
|
68
|
+
blockMap.set(smartFilter.output.ownerBlock.name, smartFilter.output.ownerBlock);
|
|
69
|
+
} else {
|
|
70
|
+
const blockDeserializer = this._blockDeserializersV1.get(serializedBlock.className);
|
|
71
|
+
if (!blockDeserializer) {
|
|
72
|
+
throw new Error(`No deserializer found for block type ${serializedBlock.className}`);
|
|
73
|
+
}
|
|
74
|
+
blockDeserializationWork.push(
|
|
75
|
+
blockDeserializer(smartFilter, serializedBlock, engine).then((newBlock) => {
|
|
76
|
+
// Deserializers are not responsible for setting the uniqueId or comments.
|
|
77
|
+
// This is so they don't have to be passed into the constructors when programmatically creating
|
|
78
|
+
// blocks, and so each deserializer doesn't have to remember to do it.
|
|
79
|
+
newBlock.uniqueId = serializedBlock.uniqueId;
|
|
80
|
+
newBlock.comments = serializedBlock.comments;
|
|
81
|
+
|
|
82
|
+
// We need to ensure any uniqueIds generated in the future (e.g. a new block is added to the SmartFilter)
|
|
83
|
+
// are higher than this one.
|
|
84
|
+
UniqueIdGenerator.EnsureIdsGreaterThan(newBlock.uniqueId);
|
|
85
|
+
|
|
86
|
+
// Save in the map
|
|
87
|
+
blockMap.set(newBlock.name, newBlock);
|
|
88
|
+
})
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
await Promise.all(blockDeserializationWork);
|
|
93
|
+
|
|
94
|
+
// Deserialize the connections
|
|
95
|
+
serializedSmartFilter.connections.forEach((connection: ISerializedConnectionV1) => {
|
|
96
|
+
// Find the source block and its connection point's connectTo function
|
|
97
|
+
const sourceBlock = blockMap.get(connection.outputBlock);
|
|
98
|
+
if (!sourceBlock) {
|
|
99
|
+
throw new Error(`Source block ${connection.outputBlock} not found`);
|
|
100
|
+
}
|
|
101
|
+
const sourceConnectionPoint = (sourceBlock as any)[connection.outputConnectionPoint];
|
|
102
|
+
if (!sourceConnectionPoint || typeof sourceConnectionPoint.connectTo !== "function") {
|
|
103
|
+
throw new Error(
|
|
104
|
+
`Block ${connection.outputBlock} does not have an connection point named ${connection.outputConnectionPoint}`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
const sourceConnectToFunction = sourceConnectionPoint.connectTo.bind(sourceConnectionPoint);
|
|
108
|
+
|
|
109
|
+
// Find the target block and its connection point
|
|
110
|
+
const targetBlock = blockMap.get(connection.inputBlock);
|
|
111
|
+
if (!targetBlock) {
|
|
112
|
+
throw new Error(`Target block ${connection.inputBlock} not found`);
|
|
113
|
+
}
|
|
114
|
+
const targetConnectionPoint = (targetBlock as any)[connection.inputConnectionPoint];
|
|
115
|
+
if (!targetConnectionPoint || typeof targetConnectionPoint !== "object") {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`Block ${connection.inputBlock} does not have a connection point named ${connection.inputConnectionPoint}`
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Create the connection
|
|
122
|
+
sourceConnectToFunction.call(sourceBlock, targetConnectionPoint);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
return smartFilter;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { SmartFilter } from "../smartFilter";
|
|
2
|
+
import type { BaseBlock } from "../blocks/baseBlock";
|
|
3
|
+
import { inputBlockSerializer } from "../blocks/inputBlock.serializer.js";
|
|
4
|
+
import type { ConnectionPoint } from "../connection/connectionPoint";
|
|
5
|
+
import { defaultBlockSerializer } from "./v1/defaultBlockSerializer.js";
|
|
6
|
+
import { OutputBlock } from "../blocks/outputBlock.js";
|
|
7
|
+
import type {
|
|
8
|
+
IBlockSerializerV1,
|
|
9
|
+
ISerializedBlockV1,
|
|
10
|
+
ISerializedConnectionV1,
|
|
11
|
+
SerializeBlockV1,
|
|
12
|
+
SerializedSmartFilterV1,
|
|
13
|
+
} from "./v1/serialization.types";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Determines if two serialized connection points are equivalent to each other
|
|
17
|
+
* @param a - The first connection point to compare
|
|
18
|
+
* @param b - The second connection point to compare
|
|
19
|
+
* @returns True if the connection points are equivalent, false otherwise
|
|
20
|
+
*/
|
|
21
|
+
function serializedConnectionPointsEqual(a: ISerializedConnectionV1, b: ISerializedConnectionV1): boolean {
|
|
22
|
+
return (
|
|
23
|
+
a.inputBlock === b.inputBlock &&
|
|
24
|
+
a.inputConnectionPoint === b.inputConnectionPoint &&
|
|
25
|
+
a.outputBlock === b.outputBlock &&
|
|
26
|
+
a.outputConnectionPoint === b.outputConnectionPoint
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Serializes SmartFilters using the latest SmartFilter serialization version.
|
|
32
|
+
* The caller passes in information necessary to serialize the blocks in the SmartFilter.
|
|
33
|
+
* This allows the caller to provide custom serializers for blocks beyond the core blocks.
|
|
34
|
+
*/
|
|
35
|
+
export class SmartFilterSerializer {
|
|
36
|
+
private readonly _blockSerializers: Map<string, SerializeBlockV1> = new Map();
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Creates a new SmartFilterSerializer
|
|
40
|
+
* @param blocksUsingDefaultSerialization - A list of the classNames of blocks which can use default serialization (they only have ConnectionPoint properties and no constructor parameters)
|
|
41
|
+
* @param additionalBlockSerializers - An array of block serializers to use, beyond those for the core blocks
|
|
42
|
+
*/
|
|
43
|
+
public constructor(blocksUsingDefaultSerialization: string[], additionalBlockSerializers: IBlockSerializerV1[]) {
|
|
44
|
+
this._blockSerializers.set(inputBlockSerializer.className, inputBlockSerializer.serialize);
|
|
45
|
+
this._blockSerializers.set(OutputBlock.ClassName, defaultBlockSerializer);
|
|
46
|
+
blocksUsingDefaultSerialization.forEach((block) => {
|
|
47
|
+
this._blockSerializers.set(block, defaultBlockSerializer);
|
|
48
|
+
});
|
|
49
|
+
additionalBlockSerializers.forEach((serializer) =>
|
|
50
|
+
this._blockSerializers.set(serializer.className, serializer.serialize)
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Serializes a SmartFilter to a JSON object of the latest version
|
|
56
|
+
* @param smartFilter - The SmartFilter to serialize
|
|
57
|
+
* @returns The serialized SmartFilter
|
|
58
|
+
*/
|
|
59
|
+
public serialize(smartFilter: SmartFilter): SerializedSmartFilterV1 {
|
|
60
|
+
const connections: ISerializedConnectionV1[] = [];
|
|
61
|
+
|
|
62
|
+
const blocks = smartFilter.attachedBlocks.map((block: BaseBlock) => {
|
|
63
|
+
// Serialize the block itself
|
|
64
|
+
const serializeFn = this._blockSerializers.get(block.getClassName());
|
|
65
|
+
if (!serializeFn) {
|
|
66
|
+
throw new Error(`No serializer was provided for a block of type ${block.getClassName()}`);
|
|
67
|
+
}
|
|
68
|
+
const serializedBlock: ISerializedBlockV1 = serializeFn(block);
|
|
69
|
+
|
|
70
|
+
// Serialize the connections to the inputs
|
|
71
|
+
block.inputs.forEach((input: ConnectionPoint) => {
|
|
72
|
+
const connectedTo = input.connectedTo;
|
|
73
|
+
if (connectedTo) {
|
|
74
|
+
const newConnection: ISerializedConnectionV1 = {
|
|
75
|
+
inputBlock: block.name,
|
|
76
|
+
inputConnectionPoint: input.name,
|
|
77
|
+
outputBlock: connectedTo.ownerBlock.name,
|
|
78
|
+
outputConnectionPoint: connectedTo.name,
|
|
79
|
+
};
|
|
80
|
+
if (!connections.find((other) => serializedConnectionPointsEqual(newConnection, other))) {
|
|
81
|
+
connections.push(newConnection);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Serialize the connections to the outputs
|
|
87
|
+
block.outputs.forEach((output: ConnectionPoint) => {
|
|
88
|
+
output.endpoints.forEach((input: ConnectionPoint) => {
|
|
89
|
+
const newConnection: ISerializedConnectionV1 = {
|
|
90
|
+
inputBlock: input.ownerBlock.name,
|
|
91
|
+
inputConnectionPoint: input.name,
|
|
92
|
+
outputBlock: block.name,
|
|
93
|
+
outputConnectionPoint: output.name,
|
|
94
|
+
};
|
|
95
|
+
if (!connections.find((other) => serializedConnectionPointsEqual(newConnection, other))) {
|
|
96
|
+
connections.push(newConnection);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return serializedBlock;
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
version: 1,
|
|
106
|
+
name: smartFilter.name,
|
|
107
|
+
comments: smartFilter.comments,
|
|
108
|
+
editorData: smartFilter.editorData,
|
|
109
|
+
blocks,
|
|
110
|
+
connections,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { BaseBlock } from "../../blocks/baseBlock";
|
|
2
|
+
import type { ISerializedBlockV1, SerializeBlockV1 } from "./serialization.types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The default V1 block serializer which can be used for any block that relies only on ConnectionPoints
|
|
6
|
+
* and does not have any constructor parameters or class properties that need to be serialized.
|
|
7
|
+
* @param block - The block to serialize
|
|
8
|
+
* @returns The serialized block
|
|
9
|
+
*/
|
|
10
|
+
export const defaultBlockSerializer: SerializeBlockV1 = (block: BaseBlock): ISerializedBlockV1 => {
|
|
11
|
+
return {
|
|
12
|
+
name: block.name,
|
|
13
|
+
uniqueId: block.uniqueId,
|
|
14
|
+
className: block.getClassName(),
|
|
15
|
+
comments: block.comments,
|
|
16
|
+
data: undefined,
|
|
17
|
+
};
|
|
18
|
+
};
|