@babylonjs/smart-filters 0.5.0-alpha → 0.6.1-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 +6 -0
- package/dist/blocks/baseBlock.d.ts.map +1 -1
- package/dist/blocks/baseBlock.js +8 -0
- package/dist/blocks/baseBlock.js.map +1 -1
- package/dist/blocks/customShaderBlock.d.ts +55 -0
- package/dist/blocks/customShaderBlock.d.ts.map +1 -0
- package/dist/blocks/customShaderBlock.js +139 -0
- package/dist/blocks/customShaderBlock.js.map +1 -0
- package/dist/blocks/inputBlock.deserializer.d.ts +1 -1
- package/dist/blocks/inputBlock.deserializer.d.ts.map +1 -1
- package/dist/blocks/inputBlock.serializer.d.ts +1 -1
- package/dist/blocks/inputBlock.serializer.d.ts.map +1 -1
- package/dist/blocks/inputBlock.serializer.js +3 -3
- package/dist/blocks/inputBlock.serializer.js.map +1 -1
- package/dist/blocks/shaderBlock.js +2 -2
- package/dist/blocks/shaderBlock.js.map +1 -1
- package/dist/command/command.d.ts +2 -3
- package/dist/command/command.d.ts.map +1 -1
- package/dist/command/command.js.map +1 -1
- package/dist/command/commandBufferDebugger.js +1 -1
- package/dist/command/commandBufferDebugger.js.map +1 -1
- package/dist/connection/connectionPointType.d.ts +4 -0
- package/dist/connection/connectionPointType.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/optimization/smartFilterOptimizer.js +3 -3
- package/dist/optimization/smartFilterOptimizer.js.map +1 -1
- package/dist/serialization/importCustomShaderBlockDefinition.d.ts +11 -0
- package/dist/serialization/importCustomShaderBlockDefinition.d.ts.map +1 -0
- package/dist/serialization/importCustomShaderBlockDefinition.js +80 -0
- package/dist/serialization/importCustomShaderBlockDefinition.js.map +1 -0
- package/dist/serialization/index.d.ts +1 -0
- package/dist/serialization/index.d.ts.map +1 -1
- package/dist/serialization/index.js +1 -0
- package/dist/serialization/index.js.map +1 -1
- package/dist/serialization/serializedBlockDefinition.d.ts +7 -0
- package/dist/serialization/serializedBlockDefinition.d.ts.map +1 -0
- package/dist/serialization/serializedBlockDefinition.js +2 -0
- package/dist/serialization/serializedBlockDefinition.js.map +1 -0
- package/dist/serialization/serializedSmartFilter.d.ts +1 -1
- package/dist/serialization/serializedSmartFilter.d.ts.map +1 -1
- package/dist/serialization/smartFilterDeserializer.d.ts +12 -4
- package/dist/serialization/smartFilterDeserializer.d.ts.map +1 -1
- package/dist/serialization/smartFilterDeserializer.js +63 -34
- package/dist/serialization/smartFilterDeserializer.js.map +1 -1
- package/dist/serialization/smartFilterSerializer.d.ts +2 -2
- package/dist/serialization/smartFilterSerializer.d.ts.map +1 -1
- package/dist/serialization/smartFilterSerializer.js +9 -6
- package/dist/serialization/smartFilterSerializer.js.map +1 -1
- package/dist/serialization/v1/blockSerialization.types.d.ts +55 -0
- package/dist/serialization/v1/blockSerialization.types.d.ts.map +1 -0
- package/dist/serialization/v1/blockSerialization.types.js +7 -0
- package/dist/serialization/v1/blockSerialization.types.js.map +1 -0
- package/dist/serialization/v1/defaultBlockSerializer.d.ts +1 -1
- package/dist/serialization/v1/defaultBlockSerializer.d.ts.map +1 -1
- package/dist/serialization/v1/defaultBlockSerializer.js +1 -1
- package/dist/serialization/v1/defaultBlockSerializer.js.map +1 -1
- package/dist/serialization/v1/index.d.ts +1 -1
- package/dist/serialization/v1/index.d.ts.map +1 -1
- package/dist/serialization/v1/index.js +1 -1
- package/dist/serialization/v1/index.js.map +1 -1
- package/dist/serialization/v1/{serialization.types.d.ts → smartFilterSerialization.types.d.ts} +12 -11
- package/dist/serialization/v1/smartFilterSerialization.types.d.ts.map +1 -0
- package/dist/serialization/v1/smartFilterSerialization.types.js +2 -0
- package/dist/serialization/v1/smartFilterSerialization.types.js.map +1 -0
- package/dist/utils/buildTools/buildShaders.js +1 -1
- package/dist/utils/buildTools/buildShaders.js.map +1 -1
- package/dist/utils/buildTools/convertShaderForHardcodedBlock.d.ts +13 -0
- package/dist/utils/buildTools/convertShaderForHardcodedBlock.d.ts.map +1 -0
- package/dist/utils/buildTools/convertShaderForHardcodedBlock.js +116 -0
- package/dist/utils/buildTools/convertShaderForHardcodedBlock.js.map +1 -0
- package/dist/utils/buildTools/shaderCode.types.d.ts +43 -0
- package/dist/utils/buildTools/shaderCode.types.d.ts.map +1 -0
- package/dist/utils/buildTools/shaderCode.types.js +2 -0
- package/dist/utils/buildTools/shaderCode.types.js.map +1 -0
- package/dist/utils/buildTools/shaderConverter.d.ts +56 -8
- package/dist/utils/buildTools/shaderConverter.d.ts.map +1 -1
- package/dist/utils/buildTools/shaderConverter.js +87 -137
- package/dist/utils/buildTools/shaderConverter.js.map +1 -1
- package/dist/utils/buildTools/watchShaders.js +2 -2
- package/dist/utils/buildTools/watchShaders.js.map +1 -1
- package/dist/utils/renderTargetUtils.js +3 -3
- package/dist/utils/renderTargetUtils.js.map +1 -1
- package/dist/utils/shaderCodeUtils.d.ts +1 -42
- package/dist/utils/shaderCodeUtils.d.ts.map +1 -1
- package/dist/utils/shaderCodeUtils.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +19 -15
- package/src/blocks/baseBlock.ts +9 -0
- package/src/blocks/customShaderBlock.ts +217 -0
- package/src/blocks/inputBlock.deserializer.ts +1 -1
- package/src/blocks/inputBlock.serializer.ts +4 -4
- package/src/blocks/shaderBlock.ts +2 -2
- package/src/command/command.ts +2 -3
- package/src/command/commandBufferDebugger.ts +1 -1
- package/src/connection/connectionPointType.ts +11 -0
- package/src/index.ts +2 -0
- package/src/optimization/smartFilterOptimizer.ts +3 -3
- package/src/serialization/importCustomShaderBlockDefinition.ts +85 -0
- package/src/serialization/index.ts +1 -0
- package/src/serialization/serializedBlockDefinition.ts +7 -0
- package/src/serialization/serializedSmartFilter.ts +1 -1
- package/src/serialization/smartFilterDeserializer.ts +106 -52
- package/src/serialization/smartFilterSerializer.ts +11 -7
- package/src/serialization/v1/blockSerialization.types.ts +63 -0
- package/src/serialization/v1/defaultBlockSerializer.ts +2 -2
- package/src/serialization/v1/index.ts +1 -1
- package/src/serialization/v1/{serialization.types.ts → smartFilterSerialization.types.ts} +11 -10
- package/src/utils/buildTools/buildShaders.ts +1 -1
- package/src/utils/buildTools/convertShaderForHardcodedBlock.ts +149 -0
- package/src/utils/buildTools/shaderCode.types.ts +49 -0
- package/src/utils/buildTools/shaderConverter.ts +158 -178
- package/src/utils/buildTools/watchShaders.ts +2 -2
- package/src/utils/renderTargetUtils.ts +3 -3
- package/src/utils/shaderCodeUtils.ts +1 -50
- package/dist/serialization/v1/serialization.types.d.ts.map +0 -1
- package/dist/serialization/v1/serialization.types.js +0 -2
- package/dist/serialization/v1/serialization.types.js.map +0 -1
|
@@ -267,7 +267,7 @@ export class SmartFilterOptimizer {
|
|
|
267
267
|
s.type === "function" &&
|
|
268
268
|
s.name === funcName &&
|
|
269
269
|
s.owners[0] &&
|
|
270
|
-
s.owners[0].
|
|
270
|
+
s.owners[0].blockType === block.blockType
|
|
271
271
|
);
|
|
272
272
|
|
|
273
273
|
const newVarName = existingRemapped?.remappedName ?? decorateSymbol(this._makeSymbolUnique(funcName));
|
|
@@ -335,7 +335,7 @@ export class SmartFilterOptimizer {
|
|
|
335
335
|
s.type === varDecl &&
|
|
336
336
|
s.name === varName &&
|
|
337
337
|
s.owners[0] &&
|
|
338
|
-
s.owners[0].
|
|
338
|
+
s.owners[0].blockType === block.blockType
|
|
339
339
|
);
|
|
340
340
|
if (existingRemapped && singleInstance) {
|
|
341
341
|
newVarName = existingRemapped.remappedName;
|
|
@@ -591,7 +591,7 @@ export class SmartFilterOptimizer {
|
|
|
591
591
|
return newShaderFuncName;
|
|
592
592
|
}
|
|
593
593
|
|
|
594
|
-
throw `Unhandled block type!
|
|
594
|
+
throw `Unhandled block type! blockType=${block.blockType}`;
|
|
595
595
|
}
|
|
596
596
|
|
|
597
597
|
private _saveBlockStackState(): void {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { ConnectionPointType } from "../connection/connectionPointType.js";
|
|
2
|
+
import { hasGlslHeader, parseFragmentShader } from "../utils/buildTools/shaderConverter.js";
|
|
3
|
+
import type { SerializedBlockDefinition } from "./serializedBlockDefinition.js";
|
|
4
|
+
import type { SerializedInputConnectionPointV1 } from "./v1/blockSerialization.types.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Imports a serialized custom shader block definition. Supports importing a JSON string
|
|
8
|
+
* of an SerializedBlockDefinition object, or a glsl shader with the required annotations
|
|
9
|
+
* so it can be converted to a SerializedBlockDefinition object.
|
|
10
|
+
* See readme.md for more information.
|
|
11
|
+
* @param serializedBlockDefinition - The serialized block definition - either a SerializedBlockDefinition object in a JSON string, or an annotated glsl shader
|
|
12
|
+
* @returns The serialized block definition
|
|
13
|
+
*/
|
|
14
|
+
export function importCustomShaderBlockDefinition(serializedBlockDefinition: string): SerializedBlockDefinition {
|
|
15
|
+
if (hasGlslHeader(serializedBlockDefinition)) {
|
|
16
|
+
return importAnnotatedGlsl(serializedBlockDefinition);
|
|
17
|
+
} else {
|
|
18
|
+
// Assume this is a serialized SerializedBlockDefinition object
|
|
19
|
+
return JSON.parse(serializedBlockDefinition);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Converts a fragment shader .glsl file to an SerializedBlockDefinition instance for use
|
|
25
|
+
* as a CustomShaderBlock. The .glsl file must contain certain annotations to be imported.
|
|
26
|
+
* See readme.md for more information.
|
|
27
|
+
* @param fragmentShader - The contents of the .glsl fragment shader file
|
|
28
|
+
* @returns The serialized block definition
|
|
29
|
+
*/
|
|
30
|
+
function importAnnotatedGlsl(fragmentShader: string): SerializedBlockDefinition {
|
|
31
|
+
const fragmentShaderInfo = parseFragmentShader(fragmentShader);
|
|
32
|
+
|
|
33
|
+
if (!fragmentShaderInfo.blockType) {
|
|
34
|
+
throw new Error("blockType must be defined");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Calculate the input connection points
|
|
38
|
+
const inputConnectionPoints: SerializedInputConnectionPointV1[] = [];
|
|
39
|
+
for (const uniform of fragmentShaderInfo.uniforms) {
|
|
40
|
+
// Convert to ConnectionPointType
|
|
41
|
+
let type: ConnectionPointType;
|
|
42
|
+
switch (uniform.type) {
|
|
43
|
+
case "float":
|
|
44
|
+
type = ConnectionPointType.Float;
|
|
45
|
+
break;
|
|
46
|
+
case "sampler2D":
|
|
47
|
+
type = ConnectionPointType.Texture;
|
|
48
|
+
break;
|
|
49
|
+
case "vec3":
|
|
50
|
+
type = ConnectionPointType.Color3;
|
|
51
|
+
break;
|
|
52
|
+
case "vec4":
|
|
53
|
+
type = ConnectionPointType.Color4;
|
|
54
|
+
break;
|
|
55
|
+
case "bool":
|
|
56
|
+
type = ConnectionPointType.Boolean;
|
|
57
|
+
break;
|
|
58
|
+
case "vec2":
|
|
59
|
+
type = ConnectionPointType.Vector2;
|
|
60
|
+
break;
|
|
61
|
+
default:
|
|
62
|
+
throw new Error(`Unsupported uniform type: '${uniform.type}'`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Add to input connection point list
|
|
66
|
+
const inputConnectionPoint: SerializedInputConnectionPointV1 = {
|
|
67
|
+
name: uniform.name,
|
|
68
|
+
type,
|
|
69
|
+
};
|
|
70
|
+
if (inputConnectionPoint.type !== ConnectionPointType.Texture && uniform.properties?.default !== undefined) {
|
|
71
|
+
inputConnectionPoint.defaultValue = uniform.properties.default;
|
|
72
|
+
}
|
|
73
|
+
inputConnectionPoints.push(inputConnectionPoint);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
formatVersion: 1,
|
|
78
|
+
blockType: fragmentShaderInfo.blockType,
|
|
79
|
+
shaderProgram: {
|
|
80
|
+
fragment: fragmentShaderInfo.shaderCode,
|
|
81
|
+
},
|
|
82
|
+
inputConnectionPoints,
|
|
83
|
+
disableOptimization: !!fragmentShaderInfo.disableOptimization,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SerializedBlockDefinitionV1 } from "./v1/blockSerialization.types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Type union of all versions of serialized SmartFilter block definitions
|
|
5
|
+
* A block definition is an object which is used to create a CustomShaderBlock instance.
|
|
6
|
+
*/
|
|
7
|
+
export type SerializedBlockDefinition = SerializedBlockDefinitionV1;
|
|
@@ -6,13 +6,22 @@ import { OutputBlock } from "../blocks/outputBlock.js";
|
|
|
6
6
|
import type { ThinEngine } from "@babylonjs/core/Engines/thinEngine";
|
|
7
7
|
import { InputBlock } from "../blocks/inputBlock.js";
|
|
8
8
|
import type {
|
|
9
|
-
DeserializeBlockV1,
|
|
10
9
|
ISerializedBlockV1,
|
|
11
10
|
ISerializedConnectionV1,
|
|
12
11
|
OptionalBlockDeserializerV1,
|
|
13
12
|
SerializedSmartFilterV1,
|
|
14
|
-
} from "./v1/
|
|
13
|
+
} from "./v1/smartFilterSerialization.types";
|
|
15
14
|
import { UniqueIdGenerator } from "../utils/uniqueIdGenerator.js";
|
|
15
|
+
import type { Nullable } from "@babylonjs/core/types";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A function that creates a block instance of the given class block type, or return null if it cannot.
|
|
19
|
+
*/
|
|
20
|
+
export type BlockFactory = (
|
|
21
|
+
smartFilter: SmartFilter,
|
|
22
|
+
engine: ThinEngine,
|
|
23
|
+
serializedBlock: ISerializedBlockV1
|
|
24
|
+
) => Promise<Nullable<BaseBlock>>;
|
|
16
25
|
|
|
17
26
|
/**
|
|
18
27
|
* Deserializes serialized SmartFilters. The caller passes in a map of block deserializers it wants to use,
|
|
@@ -20,39 +29,17 @@ import { UniqueIdGenerator } from "../utils/uniqueIdGenerator.js";
|
|
|
20
29
|
* The deserializer supports versioned serialized SmartFilters.
|
|
21
30
|
*/
|
|
22
31
|
export class SmartFilterDeserializer {
|
|
23
|
-
private readonly
|
|
32
|
+
private readonly _blockFactory: BlockFactory;
|
|
33
|
+
private readonly _customInputBlockDeserializer?: OptionalBlockDeserializerV1;
|
|
24
34
|
|
|
25
35
|
/**
|
|
26
36
|
* Creates a new SmartFilterDeserializer
|
|
27
|
-
* @param
|
|
37
|
+
* @param blockFactory - A function that creates a block of the given class name, or returns null if it cannot
|
|
28
38
|
* @param customInputBlockDeserializer - An optional custom deserializer for InputBlocks - if supplied and it returns null, the default deserializer will be used
|
|
29
39
|
*/
|
|
30
|
-
public constructor(
|
|
31
|
-
|
|
32
|
-
customInputBlockDeserializer
|
|
33
|
-
) {
|
|
34
|
-
this._blockDeserializersV1 = blockDeserializers;
|
|
35
|
-
|
|
36
|
-
this._blockDeserializersV1.set(
|
|
37
|
-
InputBlock.ClassName,
|
|
38
|
-
async (smartFilter: SmartFilter, serializedBlock: ISerializedBlockV1, engine: ThinEngine) => {
|
|
39
|
-
if (customInputBlockDeserializer) {
|
|
40
|
-
const customDeserializerResult = await customInputBlockDeserializer(
|
|
41
|
-
smartFilter,
|
|
42
|
-
serializedBlock,
|
|
43
|
-
engine
|
|
44
|
-
);
|
|
45
|
-
if (customDeserializerResult !== null) {
|
|
46
|
-
return customDeserializerResult;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return inputBlockDeserializer(smartFilter, serializedBlock);
|
|
50
|
-
}
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
this._blockDeserializersV1.set(OutputBlock.ClassName, (smartFilter: SmartFilter) =>
|
|
54
|
-
Promise.resolve(smartFilter.output.ownerBlock)
|
|
55
|
-
);
|
|
40
|
+
public constructor(blockFactory: BlockFactory, customInputBlockDeserializer?: OptionalBlockDeserializerV1) {
|
|
41
|
+
this._blockFactory = blockFactory;
|
|
42
|
+
this._customInputBlockDeserializer = customInputBlockDeserializer;
|
|
56
43
|
}
|
|
57
44
|
|
|
58
45
|
/**
|
|
@@ -63,7 +50,14 @@ export class SmartFilterDeserializer {
|
|
|
63
50
|
*/
|
|
64
51
|
public async deserialize(engine: ThinEngine, smartFilterJson: any): Promise<SmartFilter> {
|
|
65
52
|
const serializedSmartFilter: SerializedSmartFilter = smartFilterJson;
|
|
66
|
-
|
|
53
|
+
|
|
54
|
+
// Back-compat for the rename of version to formatVersion, didn't warrant a new version
|
|
55
|
+
if ((serializedSmartFilter as any).version && serializedSmartFilter.formatVersion === undefined) {
|
|
56
|
+
serializedSmartFilter.formatVersion = (serializedSmartFilter as any).version;
|
|
57
|
+
delete (serializedSmartFilter as any).version;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
switch (serializedSmartFilter.formatVersion) {
|
|
67
61
|
case 1:
|
|
68
62
|
return await this._deserializeV1(engine, serializedSmartFilter);
|
|
69
63
|
}
|
|
@@ -85,31 +79,28 @@ export class SmartFilterDeserializer {
|
|
|
85
79
|
|
|
86
80
|
// Deserialize the blocks
|
|
87
81
|
const blockDeserializationWork: Promise<void>[] = [];
|
|
82
|
+
const blockDefinitionsWhichCouldNotBeDeserialized: string[] = [];
|
|
88
83
|
serializedSmartFilter.blocks.forEach((serializedBlock: ISerializedBlockV1) => {
|
|
89
|
-
const blockDeserializer = this._blockDeserializersV1.get(serializedBlock.className);
|
|
90
|
-
if (!blockDeserializer) {
|
|
91
|
-
throw new Error(`No deserializer found for block type ${serializedBlock.className}`);
|
|
92
|
-
}
|
|
93
84
|
blockDeserializationWork.push(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
// are higher than this one.
|
|
103
|
-
UniqueIdGenerator.EnsureIdsGreaterThan(newBlock.uniqueId);
|
|
104
|
-
|
|
105
|
-
// Save in the map
|
|
106
|
-
blockIdMap.set(newBlock.uniqueId, newBlock);
|
|
107
|
-
blockNameMap.set(newBlock.name, newBlock);
|
|
108
|
-
})
|
|
85
|
+
this._deserializeBlockV1(
|
|
86
|
+
smartFilter,
|
|
87
|
+
serializedBlock,
|
|
88
|
+
engine,
|
|
89
|
+
blockDefinitionsWhichCouldNotBeDeserialized,
|
|
90
|
+
blockIdMap,
|
|
91
|
+
blockNameMap
|
|
92
|
+
)
|
|
109
93
|
);
|
|
110
94
|
});
|
|
111
95
|
await Promise.all(blockDeserializationWork);
|
|
112
96
|
|
|
97
|
+
// If any block definitions could not be deserialized, throw an error
|
|
98
|
+
if (blockDefinitionsWhichCouldNotBeDeserialized.length > 0) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
`Could not deserialize the following block definitions: ${blockDefinitionsWhichCouldNotBeDeserialized.join(", ")}`
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
113
104
|
// Deserialize the connections
|
|
114
105
|
serializedSmartFilter.connections.forEach((connection: ISerializedConnectionV1) => {
|
|
115
106
|
// Find the source block and its connection point's connectTo function
|
|
@@ -121,7 +112,9 @@ export class SmartFilterDeserializer {
|
|
|
121
112
|
if (!sourceBlock) {
|
|
122
113
|
throw new Error(`Source block ${connection.outputBlock} not found`);
|
|
123
114
|
}
|
|
124
|
-
const sourceConnectionPoint =
|
|
115
|
+
const sourceConnectionPoint = sourceBlock.outputs.find(
|
|
116
|
+
(output) => output.name === connection.outputConnectionPoint
|
|
117
|
+
);
|
|
125
118
|
if (!sourceConnectionPoint || typeof sourceConnectionPoint.connectTo !== "function") {
|
|
126
119
|
throw new Error(
|
|
127
120
|
`Block ${connection.outputBlock} does not have an connection point named ${connection.outputConnectionPoint}`
|
|
@@ -137,7 +130,10 @@ export class SmartFilterDeserializer {
|
|
|
137
130
|
if (!targetBlock) {
|
|
138
131
|
throw new Error(`Target block ${connection.inputBlock} not found`);
|
|
139
132
|
}
|
|
140
|
-
|
|
133
|
+
|
|
134
|
+
const targetConnectionPoint = targetBlock.inputs.find(
|
|
135
|
+
(input) => input.name === connection.inputConnectionPoint
|
|
136
|
+
);
|
|
141
137
|
if (!targetConnectionPoint || typeof targetConnectionPoint !== "object") {
|
|
142
138
|
throw new Error(
|
|
143
139
|
`Block ${connection.inputBlock} does not have a connection point named ${connection.inputConnectionPoint}`
|
|
@@ -150,4 +146,62 @@ export class SmartFilterDeserializer {
|
|
|
150
146
|
|
|
151
147
|
return smartFilter;
|
|
152
148
|
}
|
|
149
|
+
|
|
150
|
+
private async _deserializeBlockV1(
|
|
151
|
+
smartFilter: SmartFilter,
|
|
152
|
+
serializedBlock: ISerializedBlockV1,
|
|
153
|
+
engine: ThinEngine,
|
|
154
|
+
blockTypesWhichCouldNotBeDeserialized: string[],
|
|
155
|
+
blockIdMap: Map<number, BaseBlock>,
|
|
156
|
+
blockNameMap: Map<string, BaseBlock>
|
|
157
|
+
): Promise<void> {
|
|
158
|
+
let newBlock: Nullable<BaseBlock> = null;
|
|
159
|
+
|
|
160
|
+
// Back compat for early Smart Filter V1 serialization where the blockType was stored in className
|
|
161
|
+
// Not worth creating a new version for this, as it's only used in the deserializer
|
|
162
|
+
if ((serializedBlock as any).className && !serializedBlock.blockType) {
|
|
163
|
+
serializedBlock.blockType = (serializedBlock as any).className;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Get the instance of the block
|
|
167
|
+
switch (serializedBlock.blockType) {
|
|
168
|
+
case InputBlock.ClassName:
|
|
169
|
+
{
|
|
170
|
+
if (this._customInputBlockDeserializer) {
|
|
171
|
+
newBlock = await this._customInputBlockDeserializer(smartFilter, serializedBlock, engine);
|
|
172
|
+
}
|
|
173
|
+
if (newBlock === null) {
|
|
174
|
+
newBlock = inputBlockDeserializer(smartFilter, serializedBlock);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
break;
|
|
178
|
+
case OutputBlock.ClassName:
|
|
179
|
+
{
|
|
180
|
+
newBlock = smartFilter.output.ownerBlock;
|
|
181
|
+
}
|
|
182
|
+
break;
|
|
183
|
+
default: {
|
|
184
|
+
// If it's not an input or output block, use the provided block factory
|
|
185
|
+
newBlock = await this._blockFactory(smartFilter, engine, serializedBlock);
|
|
186
|
+
if (!newBlock) {
|
|
187
|
+
blockTypesWhichCouldNotBeDeserialized.push(serializedBlock.blockType);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Deserializers are not responsible for setting the uniqueId or comments.
|
|
194
|
+
// This is so they don't have to be passed into the constructors when programmatically creating
|
|
195
|
+
// blocks, and so each deserializer doesn't have to remember to do it.
|
|
196
|
+
newBlock.uniqueId = serializedBlock.uniqueId;
|
|
197
|
+
newBlock.comments = serializedBlock.comments;
|
|
198
|
+
|
|
199
|
+
// We need to ensure any uniqueIds generated in the future (e.g. a new block is added to the SmartFilter)
|
|
200
|
+
// are higher than this one.
|
|
201
|
+
UniqueIdGenerator.EnsureIdsGreaterThan(newBlock.uniqueId);
|
|
202
|
+
|
|
203
|
+
// Save in the map
|
|
204
|
+
blockIdMap.set(newBlock.uniqueId, newBlock);
|
|
205
|
+
blockNameMap.set(newBlock.name, newBlock);
|
|
206
|
+
}
|
|
153
207
|
}
|
|
@@ -10,7 +10,8 @@ import type {
|
|
|
10
10
|
ISerializedConnectionV1,
|
|
11
11
|
SerializeBlockV1,
|
|
12
12
|
SerializedSmartFilterV1,
|
|
13
|
-
} from "./v1/
|
|
13
|
+
} from "./v1/smartFilterSerialization.types";
|
|
14
|
+
import { CustomShaderBlock } from "../blocks/customShaderBlock.js";
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Determines if two serialized connection points are equivalent to each other
|
|
@@ -37,17 +38,17 @@ export class SmartFilterSerializer {
|
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* Creates a new SmartFilterSerializer
|
|
40
|
-
* @param blocksUsingDefaultSerialization - A list of the
|
|
41
|
+
* @param blocksUsingDefaultSerialization - A list of the blockType of blocks which can use default serialization (they only have ConnectionPoint properties and no constructor parameters)
|
|
41
42
|
* @param additionalBlockSerializers - An array of block serializers to use, beyond those for the core blocks
|
|
42
43
|
*/
|
|
43
44
|
public constructor(blocksUsingDefaultSerialization: string[], additionalBlockSerializers: IBlockSerializerV1[]) {
|
|
44
|
-
this._blockSerializers.set(inputBlockSerializer.
|
|
45
|
+
this._blockSerializers.set(inputBlockSerializer.blockType, inputBlockSerializer.serialize);
|
|
45
46
|
this._blockSerializers.set(OutputBlock.ClassName, defaultBlockSerializer);
|
|
46
47
|
blocksUsingDefaultSerialization.forEach((block) => {
|
|
47
48
|
this._blockSerializers.set(block, defaultBlockSerializer);
|
|
48
49
|
});
|
|
49
50
|
additionalBlockSerializers.forEach((serializer) =>
|
|
50
|
-
this._blockSerializers.set(serializer.
|
|
51
|
+
this._blockSerializers.set(serializer.blockType, serializer.serialize)
|
|
51
52
|
);
|
|
52
53
|
}
|
|
53
54
|
|
|
@@ -61,9 +62,12 @@ export class SmartFilterSerializer {
|
|
|
61
62
|
|
|
62
63
|
const blocks = smartFilter.attachedBlocks.map((block: BaseBlock) => {
|
|
63
64
|
// Serialize the block itself
|
|
64
|
-
const serializeFn =
|
|
65
|
+
const serializeFn =
|
|
66
|
+
block.getClassName() === CustomShaderBlock.ClassName
|
|
67
|
+
? defaultBlockSerializer
|
|
68
|
+
: this._blockSerializers.get(block.blockType);
|
|
65
69
|
if (!serializeFn) {
|
|
66
|
-
throw new Error(`No serializer was provided for a block of type ${block.
|
|
70
|
+
throw new Error(`No serializer was provided for a block of type ${block.blockType}`);
|
|
67
71
|
}
|
|
68
72
|
const serializedBlock: ISerializedBlockV1 = serializeFn(block);
|
|
69
73
|
|
|
@@ -102,7 +106,7 @@ export class SmartFilterSerializer {
|
|
|
102
106
|
});
|
|
103
107
|
|
|
104
108
|
return {
|
|
105
|
-
|
|
109
|
+
formatVersion: 1,
|
|
106
110
|
name: smartFilter.name,
|
|
107
111
|
comments: smartFilter.comments,
|
|
108
112
|
editorData: smartFilter.editorData,
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Data Types Used For Block Serialization
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { AllConnectionPointTypes, ConnectionPointValue } from "../../connection/connectionPointType";
|
|
8
|
+
import type { ShaderProgram } from "../../utils/shaderCodeUtils";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The V1 definition of a serialized block. A block definition is loaded by a CustomShaderBlock and defines how a
|
|
12
|
+
* blockType works. This should not be confused with an ISerializedBockV1, which is a serialized instance of a block in a
|
|
13
|
+
* serialized SmartFilter graph. It is referenced by blockType in a serialized SmartFilter.
|
|
14
|
+
*/
|
|
15
|
+
export type SerializedBlockDefinitionV1 = {
|
|
16
|
+
/**
|
|
17
|
+
* The version of the block definition format (format of the serialized data, not the version of the block definition itself).
|
|
18
|
+
*/
|
|
19
|
+
formatVersion: 1;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The type used to refer to the block in serialized SmartFilters and in the editor UI.
|
|
23
|
+
* The application doing the deserialization will use this to instantiate the correct block definition.
|
|
24
|
+
* Block types are expected to be unique and their behavior should be semantically equivalent across implementations
|
|
25
|
+
* (their results must be similar enough that the differences are not perceivable).
|
|
26
|
+
*/
|
|
27
|
+
blockType: string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The shader program for the block.
|
|
31
|
+
*/
|
|
32
|
+
shaderProgram: ShaderProgram;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The input connection points of the block.
|
|
36
|
+
*/
|
|
37
|
+
inputConnectionPoints: SerializedInputConnectionPointV1[];
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* If true, the optimizer will not attempt to optimize this block.
|
|
41
|
+
*/
|
|
42
|
+
disableOptimization: boolean;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A V1 input connection point of a serialized block definition.
|
|
47
|
+
*/
|
|
48
|
+
export type SerializedInputConnectionPointV1<U extends AllConnectionPointTypes = AllConnectionPointTypes> = {
|
|
49
|
+
/**
|
|
50
|
+
* The name of the connection point.
|
|
51
|
+
*/
|
|
52
|
+
name: string;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The type of the connection point.
|
|
56
|
+
*/
|
|
57
|
+
type: U;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The optional default value of the connection point.
|
|
61
|
+
*/
|
|
62
|
+
defaultValue?: ConnectionPointValue<U>;
|
|
63
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BaseBlock } from "../../blocks/baseBlock";
|
|
2
|
-
import type { ISerializedBlockV1, SerializeBlockV1 } from "./
|
|
2
|
+
import type { ISerializedBlockV1, SerializeBlockV1 } from "./smartFilterSerialization.types";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* The default V1 block serializer which can be used for any block that relies only on ConnectionPoints
|
|
@@ -11,7 +11,7 @@ export const defaultBlockSerializer: SerializeBlockV1 = (block: BaseBlock): ISer
|
|
|
11
11
|
return {
|
|
12
12
|
name: block.name,
|
|
13
13
|
uniqueId: block.uniqueId,
|
|
14
|
-
|
|
14
|
+
blockType: block.blockType,
|
|
15
15
|
comments: block.comments,
|
|
16
16
|
data: undefined,
|
|
17
17
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from "./defaultBlockSerializer.js";
|
|
2
|
-
export * from "./
|
|
2
|
+
export * from "./smartFilterSerialization.types.js";
|
|
@@ -14,8 +14,8 @@ import type { IEditorData } from "@babylonjs/shared-ui-components/nodeGraphSyste
|
|
|
14
14
|
* V1 Serialized Smart Filter
|
|
15
15
|
*/
|
|
16
16
|
export type SerializedSmartFilterV1 = {
|
|
17
|
-
/** The version of the serialized data
|
|
18
|
-
|
|
17
|
+
/** The format version of the serialized data (not the version of the SmartFilter itself).*/
|
|
18
|
+
formatVersion: 1;
|
|
19
19
|
|
|
20
20
|
/** The SmartFilter name */
|
|
21
21
|
name: string;
|
|
@@ -34,7 +34,8 @@ export type SerializedSmartFilterV1 = {
|
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* V1
|
|
37
|
+
* V1 format of a block in a serialized Smart Filter.
|
|
38
|
+
* Not to be confused with a SerializedBlockDefinitionV1 which serializes the definition of a CustomShaderBlock.
|
|
38
39
|
*/
|
|
39
40
|
export interface ISerializedBlockV1 {
|
|
40
41
|
/** The name of the block */
|
|
@@ -43,8 +44,8 @@ export interface ISerializedBlockV1 {
|
|
|
43
44
|
/** The unique ID of the block - correlates with the ID in the editorData for block position, etc. */
|
|
44
45
|
uniqueId: number;
|
|
45
46
|
|
|
46
|
-
/** The
|
|
47
|
-
|
|
47
|
+
/** The blockType of the block - used to determine how to instantiate the block during deserialization */
|
|
48
|
+
blockType: string;
|
|
48
49
|
|
|
49
50
|
/** The comments for the block */
|
|
50
51
|
comments: Nullable<string>;
|
|
@@ -82,13 +83,13 @@ export interface ISerializedConnectionV1 {
|
|
|
82
83
|
export type SerializeBlockV1 = (block: BaseBlock) => ISerializedBlockV1;
|
|
83
84
|
|
|
84
85
|
/**
|
|
85
|
-
* A V1
|
|
86
|
+
* A V1 serializer for blocks in a SmartFilter
|
|
86
87
|
*/
|
|
87
88
|
export interface IBlockSerializerV1 {
|
|
88
|
-
/** The
|
|
89
|
-
|
|
89
|
+
/** The blockType of the block that this serializer can serialize */
|
|
90
|
+
blockType: string;
|
|
90
91
|
|
|
91
|
-
/** The function that serializes the block */
|
|
92
|
+
/** The function that serializes the block in the Smart Filter */
|
|
92
93
|
serialize: SerializeBlockV1;
|
|
93
94
|
}
|
|
94
95
|
|
|
@@ -99,7 +100,7 @@ export interface IBlockSerializerV1 {
|
|
|
99
100
|
*/
|
|
100
101
|
|
|
101
102
|
/**
|
|
102
|
-
* A function that deserializes a block
|
|
103
|
+
* A function that deserializes a V1 block in a SmartFilter
|
|
103
104
|
*/
|
|
104
105
|
export type DeserializeBlockV1 = (
|
|
105
106
|
smartFilter: SmartFilter,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @example node buildShaders.js <shaderPath> <importPath>
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { convertShaders } from "./
|
|
8
|
+
import { convertShaders } from "./convertShaderForHardcodedBlock.js";
|
|
9
9
|
|
|
10
10
|
const externalArguments = process.argv.slice(2);
|
|
11
11
|
if (externalArguments.length >= 2 && externalArguments[0] && externalArguments[1]) {
|