@babylonjs/core 8.37.0 → 8.37.1

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 (193) hide show
  1. package/Animations/animationGroup.js +1 -4
  2. package/Animations/animationGroup.js.map +1 -1
  3. package/Behaviors/Cameras/interpolatingBehavior.d.ts +58 -0
  4. package/Behaviors/Cameras/interpolatingBehavior.js +157 -0
  5. package/Behaviors/Cameras/interpolatingBehavior.js.map +1 -0
  6. package/Cameras/Inputs/arcRotateCameraPointersInput.d.ts +5 -20
  7. package/Cameras/Inputs/arcRotateCameraPointersInput.js +9 -69
  8. package/Cameras/Inputs/arcRotateCameraPointersInput.js.map +1 -1
  9. package/Cameras/Inputs/geospatialCameraKeyboardInput.d.ts +81 -0
  10. package/Cameras/Inputs/geospatialCameraKeyboardInput.js +223 -0
  11. package/Cameras/Inputs/geospatialCameraKeyboardInput.js.map +1 -0
  12. package/Cameras/Inputs/geospatialCameraMouseWheelInput.js +1 -1
  13. package/Cameras/Inputs/geospatialCameraMouseWheelInput.js.map +1 -1
  14. package/Cameras/Inputs/geospatialCameraPointersInput.d.ts +17 -21
  15. package/Cameras/Inputs/geospatialCameraPointersInput.js +49 -71
  16. package/Cameras/Inputs/geospatialCameraPointersInput.js.map +1 -1
  17. package/Cameras/Inputs/orbitCameraPointersInput.d.ts +49 -0
  18. package/Cameras/Inputs/orbitCameraPointersInput.js +105 -0
  19. package/Cameras/Inputs/orbitCameraPointersInput.js.map +1 -0
  20. package/Cameras/Limits/geospatialLimits.d.ts +60 -0
  21. package/Cameras/Limits/geospatialLimits.js +89 -0
  22. package/Cameras/Limits/geospatialLimits.js.map +1 -0
  23. package/Cameras/cameraMovement.d.ts +150 -0
  24. package/Cameras/cameraMovement.js +190 -0
  25. package/Cameras/cameraMovement.js.map +1 -0
  26. package/Cameras/geospatialCamera.d.ts +78 -49
  27. package/Cameras/geospatialCamera.js +210 -191
  28. package/Cameras/geospatialCamera.js.map +1 -1
  29. package/Cameras/geospatialCameraInputsManager.d.ts +5 -0
  30. package/Cameras/geospatialCameraInputsManager.js +9 -0
  31. package/Cameras/geospatialCameraInputsManager.js.map +1 -1
  32. package/Cameras/geospatialCameraMovement.d.ts +66 -0
  33. package/Cameras/geospatialCameraMovement.js +199 -0
  34. package/Cameras/geospatialCameraMovement.js.map +1 -0
  35. package/Decorators/nodeDecorator.d.ts +9 -7
  36. package/Decorators/nodeDecorator.js +9 -7
  37. package/Decorators/nodeDecorator.js.map +1 -1
  38. package/Engines/Native/nativeInterfaces.d.ts +14 -6
  39. package/Engines/Native/nativeInterfaces.js +6 -1
  40. package/Engines/Native/nativeInterfaces.js.map +1 -1
  41. package/Engines/WebGPU/webgpuTextureManager.js +2 -2
  42. package/Engines/WebGPU/webgpuTextureManager.js.map +1 -1
  43. package/Engines/abstractEngine.js +2 -2
  44. package/Engines/abstractEngine.js.map +1 -1
  45. package/Engines/nativeEngine.js +2 -2
  46. package/Engines/nativeEngine.js.map +1 -1
  47. package/FlowGraph/Blocks/Data/Math/flowGraphVectorMathBlocks.js +1 -1
  48. package/FlowGraph/Blocks/Data/Math/flowGraphVectorMathBlocks.js.map +1 -1
  49. package/FlowGraph/flowGraphMath.d.ts +25 -0
  50. package/FlowGraph/flowGraphMath.js +40 -0
  51. package/FlowGraph/flowGraphMath.js.map +1 -0
  52. package/FrameGraph/Node/Blocks/Layers/glowLayerBlock.js +1 -1
  53. package/FrameGraph/Node/Blocks/Layers/glowLayerBlock.js.map +1 -1
  54. package/FrameGraph/Node/Blocks/Layers/highlightLayerBlock.js +1 -1
  55. package/FrameGraph/Node/Blocks/Layers/highlightLayerBlock.js.map +1 -1
  56. package/FrameGraph/Node/Blocks/PostProcesses/basePostProcessBlock.js +1 -1
  57. package/FrameGraph/Node/Blocks/PostProcesses/baseWithPropertiesPostProcessBlock.js +1 -1
  58. package/FrameGraph/Node/Blocks/PostProcesses/circleOfConfusionPostProcessBlock.js +1 -1
  59. package/FrameGraph/Node/Blocks/PostProcesses/colorCorrectionPostProcessBlock.js +1 -1
  60. package/FrameGraph/Node/Blocks/PostProcesses/depthOfFieldPostProcessBlock.js +1 -1
  61. package/FrameGraph/Node/Blocks/PostProcesses/filterPostProcessBlock.js +1 -1
  62. package/FrameGraph/Node/Blocks/PostProcesses/imageProcessingPostProcessBlock.js +1 -1
  63. package/FrameGraph/Node/Blocks/PostProcesses/ssao2PostProcessBlock.js +1 -1
  64. package/FrameGraph/Node/Blocks/PostProcesses/ssao2PostProcessBlock.js.map +1 -1
  65. package/FrameGraph/Node/Blocks/PostProcesses/ssrPostProcessBlock.js +1 -1
  66. package/FrameGraph/Node/Blocks/PostProcesses/ssrPostProcessBlock.js.map +1 -1
  67. package/FrameGraph/Node/Blocks/Rendering/baseObjectRendererBlock.d.ts +6 -0
  68. package/FrameGraph/Node/Blocks/Rendering/baseObjectRendererBlock.js +26 -0
  69. package/FrameGraph/Node/Blocks/Rendering/baseObjectRendererBlock.js.map +1 -1
  70. package/FrameGraph/Node/Blocks/Rendering/geometryRendererBlock.d.ts +6 -0
  71. package/FrameGraph/Node/Blocks/Rendering/geometryRendererBlock.js +48 -22
  72. package/FrameGraph/Node/Blocks/Rendering/geometryRendererBlock.js.map +1 -1
  73. package/FrameGraph/Node/Blocks/Textures/clearBlock.js +3 -3
  74. package/FrameGraph/Node/Blocks/Textures/clearBlock.js.map +1 -1
  75. package/FrameGraph/Node/Blocks/Textures/copyTextureBlock.js +1 -1
  76. package/FrameGraph/Node/Blocks/Textures/generateMipmapsBlock.js +1 -1
  77. package/FrameGraph/Node/Blocks/Textures/generateMipmapsBlock.js.map +1 -1
  78. package/FrameGraph/Node/nodeRenderGraph.js +2 -1
  79. package/FrameGraph/Node/nodeRenderGraph.js.map +1 -1
  80. package/FrameGraph/Passes/{cullPass.d.ts → objectListPass.d.ts} +8 -8
  81. package/FrameGraph/Passes/{cullPass.js → objectListPass.js} +9 -9
  82. package/FrameGraph/Passes/objectListPass.js.map +1 -0
  83. package/FrameGraph/Passes/renderPass.d.ts +6 -2
  84. package/FrameGraph/Passes/renderPass.js +14 -2
  85. package/FrameGraph/Passes/renderPass.js.map +1 -1
  86. package/FrameGraph/Tasks/Misc/cullObjectsTask.js +2 -2
  87. package/FrameGraph/Tasks/Misc/cullObjectsTask.js.map +1 -1
  88. package/FrameGraph/Tasks/Rendering/geometryRendererTask.d.ts +8 -0
  89. package/FrameGraph/Tasks/Rendering/geometryRendererTask.js +10 -0
  90. package/FrameGraph/Tasks/Rendering/geometryRendererTask.js.map +1 -1
  91. package/FrameGraph/Tasks/Rendering/objectRendererTask.d.ts +8 -0
  92. package/FrameGraph/Tasks/Rendering/objectRendererTask.js +13 -0
  93. package/FrameGraph/Tasks/Rendering/objectRendererTask.js.map +1 -1
  94. package/FrameGraph/Tasks/Texture/clearTextureTask.d.ts +1 -1
  95. package/FrameGraph/Tasks/Texture/clearTextureTask.js +7 -5
  96. package/FrameGraph/Tasks/Texture/clearTextureTask.js.map +1 -1
  97. package/FrameGraph/frameGraph.d.ts +10 -4
  98. package/FrameGraph/frameGraph.js +22 -9
  99. package/FrameGraph/frameGraph.js.map +1 -1
  100. package/FrameGraph/frameGraphTask.js +3 -3
  101. package/FrameGraph/frameGraphTask.js.map +1 -1
  102. package/FrameGraph/index.d.ts +1 -1
  103. package/FrameGraph/index.js +1 -1
  104. package/FrameGraph/index.js.map +1 -1
  105. package/Materials/GaussianSplatting/gaussianSplattingMaterial.js +1 -1
  106. package/Materials/GaussianSplatting/gaussianSplattingMaterial.js.map +1 -1
  107. package/Materials/Node/Blocks/GaussianSplatting/gaussianSplattingBlock.js +5 -1
  108. package/Materials/Node/Blocks/GaussianSplatting/gaussianSplattingBlock.js.map +1 -1
  109. package/Materials/Node/Blocks/GaussianSplatting/splatReaderBlock.js +6 -5
  110. package/Materials/Node/Blocks/GaussianSplatting/splatReaderBlock.js.map +1 -1
  111. package/Materials/shaderMaterial.d.ts +9 -0
  112. package/Materials/shaderMaterial.js +39 -2
  113. package/Materials/shaderMaterial.js.map +1 -1
  114. package/Maths/math.vector.functions.d.ts +5 -24
  115. package/Maths/math.vector.functions.js +32 -35
  116. package/Maths/math.vector.functions.js.map +1 -1
  117. package/Meshes/GaussianSplatting/gaussianSplattingMesh.d.ts +1 -0
  118. package/Meshes/GaussianSplatting/gaussianSplattingMesh.js +51 -16
  119. package/Meshes/GaussianSplatting/gaussianSplattingMesh.js.map +1 -1
  120. package/Meshes/csg2.js +1 -1
  121. package/Meshes/csg2.js.map +1 -1
  122. package/Meshes/thinInstanceMesh.js +15 -0
  123. package/Meshes/thinInstanceMesh.js.map +1 -1
  124. package/Misc/fileTools.js.map +1 -1
  125. package/Misc/tools.d.ts +3 -0
  126. package/Misc/tools.js +43 -4
  127. package/Misc/tools.js.map +1 -1
  128. package/Particles/EmitterTypes/coneParticleEmitter.d.ts +3 -1
  129. package/Particles/EmitterTypes/coneParticleEmitter.js +7 -1
  130. package/Particles/EmitterTypes/coneParticleEmitter.js.map +1 -1
  131. package/Particles/Node/Blocks/Emitters/coneShapeBlock.d.ts +9 -0
  132. package/Particles/Node/Blocks/Emitters/coneShapeBlock.js +43 -12
  133. package/Particles/Node/Blocks/Emitters/coneShapeBlock.js.map +1 -1
  134. package/Particles/Node/Blocks/Update/basicColorUpdateBlock.d.ts +1 -1
  135. package/Particles/Node/Blocks/Update/basicColorUpdateBlock.js +1 -1
  136. package/Particles/Node/Blocks/Update/basicColorUpdateBlock.js.map +1 -1
  137. package/Particles/Node/Blocks/Update/basicPositionUpdateBlock.d.ts +1 -1
  138. package/Particles/Node/Blocks/Update/basicPositionUpdateBlock.js +3 -3
  139. package/Particles/Node/Blocks/Update/basicPositionUpdateBlock.js.map +1 -1
  140. package/Particles/Node/Blocks/Update/updateSizeBlock.d.ts +35 -0
  141. package/Particles/Node/Blocks/Update/updateSizeBlock.js +73 -0
  142. package/Particles/Node/Blocks/Update/updateSizeBlock.js.map +1 -0
  143. package/Particles/Node/Blocks/index.d.ts +1 -0
  144. package/Particles/Node/Blocks/index.js +1 -0
  145. package/Particles/Node/Blocks/index.js.map +1 -1
  146. package/Particles/Node/Blocks/particleInputBlock.js +2 -0
  147. package/Particles/Node/Blocks/particleInputBlock.js.map +1 -1
  148. package/Particles/Node/Blocks/particleRandomBlock.d.ts +5 -2
  149. package/Particles/Node/Blocks/particleRandomBlock.js +32 -14
  150. package/Particles/Node/Blocks/particleRandomBlock.js.map +1 -1
  151. package/Particles/Node/Blocks/systemBlock.d.ts +20 -12
  152. package/Particles/Node/Blocks/systemBlock.js +26 -22
  153. package/Particles/Node/Blocks/systemBlock.js.map +1 -1
  154. package/Particles/Node/Enums/nodeParticleContextualSources.d.ts +5 -1
  155. package/Particles/Node/Enums/nodeParticleContextualSources.js +4 -0
  156. package/Particles/Node/Enums/nodeParticleContextualSources.js.map +1 -1
  157. package/Particles/Node/nodeParticleBuildState.d.ts +5 -5
  158. package/Particles/Node/nodeParticleBuildState.js +11 -7
  159. package/Particles/Node/nodeParticleBuildState.js.map +1 -1
  160. package/Particles/Node/nodeParticleSystemSet.helper.d.ts +0 -2
  161. package/Particles/Node/nodeParticleSystemSet.helper.js +524 -147
  162. package/Particles/Node/nodeParticleSystemSet.helper.js.map +1 -1
  163. package/Particles/particle.d.ts +4 -0
  164. package/Particles/particle.js +2 -0
  165. package/Particles/particle.js.map +1 -1
  166. package/Particles/thinParticleSystem.d.ts +3 -7
  167. package/Particles/thinParticleSystem.function.d.ts +1 -1
  168. package/Particles/thinParticleSystem.function.js +9 -6
  169. package/Particles/thinParticleSystem.function.js.map +1 -1
  170. package/Particles/thinParticleSystem.js +5 -7
  171. package/Particles/thinParticleSystem.js.map +1 -1
  172. package/Shaders/ShadersInclude/gaussianSplatting.js +5 -1
  173. package/Shaders/ShadersInclude/gaussianSplatting.js.map +1 -1
  174. package/Shaders/ShadersInclude/gaussianSplattingUboDeclaration.js +2 -1
  175. package/Shaders/ShadersInclude/gaussianSplattingUboDeclaration.js.map +1 -1
  176. package/Shaders/ShadersInclude/gaussianSplattingVertexDeclaration.js +1 -1
  177. package/Shaders/ShadersInclude/gaussianSplattingVertexDeclaration.js.map +1 -1
  178. package/Shaders/gaussianSplatting.vertex.js +3 -3
  179. package/Shaders/gaussianSplatting.vertex.js.map +1 -1
  180. package/Shaders/gaussianSplattingDepth.vertex.js +2 -2
  181. package/Shaders/gaussianSplattingDepth.vertex.js.map +1 -1
  182. package/ShadersWGSL/ShadersInclude/gaussianSplatting.js +35 -1
  183. package/ShadersWGSL/ShadersInclude/gaussianSplatting.js.map +1 -1
  184. package/ShadersWGSL/ShadersInclude/gaussianSplattingUboDeclaration.js +2 -1
  185. package/ShadersWGSL/ShadersInclude/gaussianSplattingUboDeclaration.js.map +1 -1
  186. package/ShadersWGSL/ShadersInclude/gaussianSplattingVertexDeclaration.js +1 -2
  187. package/ShadersWGSL/ShadersInclude/gaussianSplattingVertexDeclaration.js.map +1 -1
  188. package/ShadersWGSL/gaussianSplatting.vertex.js +3 -3
  189. package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
  190. package/ShadersWGSL/gaussianSplattingDepth.vertex.js +2 -2
  191. package/ShadersWGSL/gaussianSplattingDepth.vertex.js.map +1 -1
  192. package/package.json +1 -1
  193. package/FrameGraph/Passes/cullPass.js.map +0 -1
@@ -10,6 +10,8 @@ import { ParticleMathBlock, ParticleMathBlockOperations } from "./Blocks/particl
10
10
  import { ParticleRandomBlock, ParticleRandomBlockLocks } from "./Blocks/particleRandomBlock.js";
11
11
  import { ParticleTextureSourceBlock } from "./Blocks/particleSourceTextureBlock.js";
12
12
  import { SystemBlock } from "./Blocks/systemBlock.js";
13
+ import { ParticleVectorLengthBlock } from "./Blocks/particleVectorLengthBlock.js";
14
+ import { ParticleConditionBlock, ParticleConditionBlockTests } from "./Blocks/Conditions/particleConditionBlock.js";
13
15
  import { CreateParticleBlock } from "./Blocks/Emitters/createParticleBlock.js";
14
16
  import { BoxShapeBlock } from "./Blocks/Emitters/boxShapeBlock.js";
15
17
  import { ConeShapeBlock } from "./Blocks/Emitters/coneShapeBlock.js";
@@ -22,13 +24,12 @@ import { UpdateAngleBlock } from "./Blocks/Update/updateAngleBlock.js";
22
24
  import { UpdateColorBlock } from "./Blocks/Update/updateColorBlock.js";
23
25
  import { UpdateDirectionBlock } from "./Blocks/Update/updateDirectionBlock.js";
24
26
  import { UpdatePositionBlock } from "./Blocks/Update/updatePositionBlock.js";
27
+ import { UpdateSizeBlock } from "./Blocks/Update/updateSizeBlock.js";
25
28
  /**
26
29
  * Converts a ParticleSystem to a NodeParticleSystemSet.
27
30
  * @param name The name of the node particle system set.
28
31
  * @param particleSystemsList The particle systems to convert.
29
32
  * @returns The converted node particle system set or null if conversion failed.
30
- * #0K3AQ2#3672
31
- * #7J0NXA#4
32
33
  */
33
34
  export async function ConvertToNodeParticleSystemSetAsync(name, particleSystemsList) {
34
35
  if (!particleSystemsList || !particleSystemsList.length) {
@@ -37,39 +38,36 @@ export async function ConvertToNodeParticleSystemSetAsync(name, particleSystemsL
37
38
  const nodeParticleSystemSet = new NodeParticleSystemSet(name);
38
39
  const promises = [];
39
40
  for (const particleSystem of particleSystemsList) {
40
- promises.push(_ExtractDatafromParticleSystemAsync(nodeParticleSystemSet, particleSystem));
41
+ promises.push(_ExtractDatafromParticleSystemAsync(nodeParticleSystemSet, particleSystem, {}));
41
42
  }
42
43
  await Promise.all(promises);
43
44
  return nodeParticleSystemSet;
44
45
  }
45
- async function _ExtractDatafromParticleSystemAsync(newSet, oldSystem) {
46
- // CreateParticle block
47
- const createParticleBlock = _CreateCreateParticleBlock(oldSystem);
46
+ async function _ExtractDatafromParticleSystemAsync(newSet, oldSystem, context) {
47
+ // CreateParticle block group
48
+ const createParticleOutput = _CreateParticleBlockGroup(oldSystem, context);
48
49
  // Emitter Shape block
49
- const shapeBlock = _CreateEmitterShapeBlock(oldSystem);
50
- createParticleBlock.particle.connectTo(shapeBlock.particle);
51
- // Update the particle position
52
- const positionUpdatedParticle = _CreateUpdateSystem(shapeBlock.output, oldSystem);
53
- // Color update
54
- const colorUpdateBlock = _CreateColorUpdateBlock(oldSystem, createParticleBlock);
55
- positionUpdatedParticle.connectTo(colorUpdateBlock.particle);
50
+ const shapeOutput = _EmitterShapeBlock(oldSystem);
51
+ createParticleOutput.particle.connectTo(shapeOutput.particle);
52
+ // UpdateParticle block group
53
+ const updateParticleOutput = _UpdateParticleBlockGroup(shapeOutput.output, oldSystem, context);
56
54
  // System block
57
- const newSystem = _CreateSystemBlock(oldSystem);
58
- colorUpdateBlock.output.connectTo(newSystem.particle);
55
+ const newSystem = _SystemBlockGroup(oldSystem, context);
56
+ updateParticleOutput.connectTo(newSystem.particle);
59
57
  // Register
60
58
  newSet.systemBlocks.push(newSystem);
61
59
  }
62
- function _CreateSystemBlock(oldSystem) {
60
+ // ------------- SYSTEM FUNCTIONS -------------
61
+ function _SystemBlockGroup(oldSystem, context) {
63
62
  const newSystem = new SystemBlock(oldSystem.name);
64
63
  _CreateAndConnectInput("Translation pivot", oldSystem.translationPivot, newSystem.translationPivot);
65
64
  _CreateAndConnectInput("Texture mask", oldSystem.textureMask, newSystem.textureMask);
65
+ _CreateTargetStopDurationInputBlock(oldSystem, context).connectTo(newSystem.targetStopDuration);
66
66
  newSystem.emitRate = oldSystem.emitRate;
67
67
  newSystem.manualEmitCount = oldSystem.manualEmitCount;
68
68
  newSystem.blendMode = oldSystem.blendMode;
69
69
  newSystem.capacity = oldSystem.getCapacity();
70
- newSystem.targetStopDuration = oldSystem.targetStopDuration;
71
70
  newSystem.startDelay = oldSystem.startDelay;
72
- newSystem.targetStopDuration = oldSystem.targetStopDuration;
73
71
  newSystem.updateSpeed = oldSystem.updateSpeed;
74
72
  newSystem.preWarmCycles = oldSystem.preWarmCycles;
75
73
  newSystem.preWarmStepOffset = oldSystem.preWarmStepOffset;
@@ -88,40 +86,149 @@ function _CreateSystemBlock(oldSystem) {
88
86
  textureBlock.texture.connectTo(newSystem.texture);
89
87
  return newSystem;
90
88
  }
91
- function _CreateCreateParticleBlock(oldSystem) {
92
- // Create particle
89
+ // ------------- CREATE PARTICLE FUNCTIONS -------------
90
+ // The creation of the different properties follows the order they are added to the CreationQueue in ThinParticleSystem:
91
+ // Lifetime, Emit Power, Size, Scale/StartSize, Angle, Color, Noise, ColorDead, Ramp, Sheet
92
+ function _CreateParticleBlockGroup(oldSystem, context) {
93
+ // Create particle block
93
94
  const createParticleBlock = new CreateParticleBlock("Create Particle");
94
- // Size
95
- const randomSizeBlock = new ParticleRandomBlock("Random size");
96
- _CreateAndConnectInput("Min size", oldSystem.minSize, randomSizeBlock.min);
97
- _CreateAndConnectInput("Max size", oldSystem.maxSize, randomSizeBlock.max);
98
- randomSizeBlock.output.connectTo(createParticleBlock.size);
99
- // Scale
100
- const randomScaleBlock = new ParticleRandomBlock("Random Scale");
101
- _CreateAndConnectInput("Min Scale", new Vector2(oldSystem.minScaleX, oldSystem.minScaleY), randomScaleBlock.min);
102
- _CreateAndConnectInput("Max Scale", new Vector2(oldSystem.maxScaleX, oldSystem.maxScaleY), randomScaleBlock.max);
103
- randomScaleBlock.output.connectTo(createParticleBlock.scale);
104
- // Color is handled when we do the color update block to manage gradients
95
+ _CreateParticleLifetimeBlockGroup(oldSystem, context).connectTo(createParticleBlock.lifeTime);
96
+ _CreateParticleEmitPowerBlockGroup(oldSystem).connectTo(createParticleBlock.emitPower);
97
+ _CreateParticleSizeBlockGroup(oldSystem, context).connectTo(createParticleBlock.size);
98
+ _CreateParticleScaleBlockGroup(oldSystem, context).connectTo(createParticleBlock.scale);
99
+ _CreateParticleAngleBlockGroup(oldSystem).connectTo(createParticleBlock.angle);
100
+ _CreateParticleColorBlockGroup(oldSystem, context).connectTo(createParticleBlock.color);
105
101
  // Dead color
106
102
  _CreateAndConnectInput("Dead Color", oldSystem.colorDead, createParticleBlock.colorDead);
107
- // Emit power (Speed)
103
+ return createParticleBlock;
104
+ }
105
+ /**
106
+ * Creates the group of blocks that represent the particle lifetime
107
+ * @param oldSystem The old particle system to convert
108
+ * @param context The context of the current conversion
109
+ * @returns The output of the group of blocks that represent the particle lifetime
110
+ */
111
+ function _CreateParticleLifetimeBlockGroup(oldSystem, context) {
112
+ if (oldSystem.targetStopDuration && oldSystem._lifeTimeGradients && oldSystem._lifeTimeGradients.length > 0) {
113
+ context.timeToStopTimeRatioBlockGroupOutput = _CreateTimeToStopTimeRatioBlockGroup(oldSystem, context);
114
+ const gradientBlockGroupOutput = _CreateGradientBlockGroup(context.timeToStopTimeRatioBlockGroupOutput, oldSystem._lifeTimeGradients, ParticleRandomBlockLocks.PerParticle, "Lifetime");
115
+ return gradientBlockGroupOutput;
116
+ }
117
+ else {
118
+ const randomLifetimeBlock = new ParticleRandomBlock("Random Lifetime");
119
+ _CreateAndConnectInput("Min Lifetime", oldSystem.minLifeTime, randomLifetimeBlock.min);
120
+ _CreateAndConnectInput("Max Lifetime", oldSystem.maxLifeTime, randomLifetimeBlock.max);
121
+ return randomLifetimeBlock.output;
122
+ }
123
+ }
124
+ /**
125
+ * Creates the group of blocks that represent the particle emit power
126
+ * @param oldSystem The old particle system to convert
127
+ * @returns The output of the group of blocks that represent the particle emit power
128
+ */
129
+ function _CreateParticleEmitPowerBlockGroup(oldSystem) {
108
130
  const randomEmitPowerBlock = new ParticleRandomBlock("Random Emit Power");
109
131
  _CreateAndConnectInput("Min Emit Power", oldSystem.minEmitPower, randomEmitPowerBlock.min);
110
132
  _CreateAndConnectInput("Max Emit Power", oldSystem.maxEmitPower, randomEmitPowerBlock.max);
111
- randomEmitPowerBlock.output.connectTo(createParticleBlock.emitPower);
112
- // Angle (rotation)
133
+ return randomEmitPowerBlock.output;
134
+ }
135
+ /**
136
+ * Creates the group of blocks that represent the particle size
137
+ * @param oldSystem The old particle system to convert
138
+ * @param context The context of the current conversion
139
+ * @returns The output of the group of blocks that represent the particle size
140
+ */
141
+ function _CreateParticleSizeBlockGroup(oldSystem, context) {
142
+ if (oldSystem._sizeGradients && oldSystem._sizeGradients.length > 0) {
143
+ context.sizeGradientValue0Output = _CreateParticleInitialValueFromGradient(oldSystem._sizeGradients);
144
+ return context.sizeGradientValue0Output;
145
+ }
146
+ else {
147
+ const randomSizeBlock = new ParticleRandomBlock("Random size");
148
+ _CreateAndConnectInput("Min size", oldSystem.minSize, randomSizeBlock.min);
149
+ _CreateAndConnectInput("Max size", oldSystem.maxSize, randomSizeBlock.max);
150
+ return randomSizeBlock.output;
151
+ }
152
+ }
153
+ /**
154
+ * Creates the group of blocks that represent the particle scale
155
+ * @param oldSystem The old particle system to convert
156
+ * @param context The context of the current conversion
157
+ * @returns The output of the group of blocks that represent the particle scale
158
+ */
159
+ function _CreateParticleScaleBlockGroup(oldSystem, context) {
160
+ // Create the random scale
161
+ const randomScaleBlock = new ParticleRandomBlock("Random Scale");
162
+ _CreateAndConnectInput("Min Scale", new Vector2(oldSystem.minScaleX, oldSystem.minScaleY), randomScaleBlock.min);
163
+ _CreateAndConnectInput("Max Scale", new Vector2(oldSystem.maxScaleX, oldSystem.maxScaleY), randomScaleBlock.max);
164
+ if (oldSystem.targetStopDuration && oldSystem._startSizeGradients && oldSystem._startSizeGradients.length > 0) {
165
+ // Create the start size gradient
166
+ context.timeToStopTimeRatioBlockGroupOutput = _CreateTimeToStopTimeRatioBlockGroup(oldSystem, context);
167
+ const gradientBlockGroupOutput = _CreateGradientBlockGroup(context.timeToStopTimeRatioBlockGroupOutput, oldSystem._startSizeGradients, ParticleRandomBlockLocks.PerParticle, "Start Size");
168
+ // Multiply the initial random scale by the start size gradient
169
+ const multiplyScaleBlock = new ParticleMathBlock("Multiply Scale by Start Size Gradient");
170
+ multiplyScaleBlock.operation = ParticleMathBlockOperations.Multiply;
171
+ randomScaleBlock.output.connectTo(multiplyScaleBlock.left);
172
+ gradientBlockGroupOutput.connectTo(multiplyScaleBlock.right);
173
+ return multiplyScaleBlock.output;
174
+ }
175
+ else {
176
+ return randomScaleBlock.output;
177
+ }
178
+ }
179
+ /**
180
+ * Creates the group of blocks that represent the particle angle (rotation)
181
+ * @param oldSystem The old particle system to convert
182
+ * @returns The output of the group of blocks that represent the particle angle (rotation)
183
+ */
184
+ function _CreateParticleAngleBlockGroup(oldSystem) {
113
185
  const randomRotationBlock = new ParticleRandomBlock("Random Rotation");
114
186
  _CreateAndConnectInput("Min Rotation", oldSystem.minInitialRotation, randomRotationBlock.min);
115
187
  _CreateAndConnectInput("Max Rotation", oldSystem.maxInitialRotation, randomRotationBlock.max);
116
- randomRotationBlock.output.connectTo(createParticleBlock.angle);
117
- // Lifetime
118
- const randomLifetimeBlock = new ParticleRandomBlock("Random Lifetime");
119
- _CreateAndConnectInput("Min Lifetime", oldSystem.minLifeTime, randomLifetimeBlock.min);
120
- _CreateAndConnectInput("Max Lifetime", oldSystem.maxLifeTime, randomLifetimeBlock.max);
121
- randomLifetimeBlock.output.connectTo(createParticleBlock.lifeTime);
122
- return createParticleBlock;
188
+ return randomRotationBlock.output;
189
+ }
190
+ /**
191
+ * Creates the group of blocks that represent the particle color
192
+ * @param oldSystem The old particle system to convert
193
+ * @param context The context of the current conversion
194
+ * @returns The output of the group of blocks that represent the particle color
195
+ */
196
+ function _CreateParticleColorBlockGroup(oldSystem, context) {
197
+ if (oldSystem._colorGradients && oldSystem._colorGradients.length > 0) {
198
+ context.colorGradientValue0Output = _CreateParticleInitialValueFromGradient(oldSystem._colorGradients);
199
+ return context.colorGradientValue0Output;
200
+ }
201
+ else {
202
+ const randomColorBlock = new ParticleRandomBlock("Random color");
203
+ _CreateAndConnectInput("Color 1", oldSystem.color1, randomColorBlock.min);
204
+ _CreateAndConnectInput("Color 2", oldSystem.color2, randomColorBlock.max);
205
+ return randomColorBlock.output;
206
+ }
207
+ }
208
+ function _CreateParticleInitialValueFromGradient(gradients) {
209
+ if (gradients.length === 0) {
210
+ throw new Error("No gradients provided.");
211
+ }
212
+ const gradientStep = gradients[0];
213
+ const value1 = gradientStep.factor1 ?? gradientStep.color1;
214
+ const value2 = gradientStep.factor2 ?? gradientStep.color2;
215
+ if (value2 !== undefined) {
216
+ // Create a random between value1 and value2
217
+ const randomBlock = new ParticleRandomBlock("Random Value 0");
218
+ randomBlock.lockMode = ParticleRandomBlockLocks.OncePerParticle;
219
+ _CreateAndConnectInput("Value 1", value1, randomBlock.min);
220
+ _CreateAndConnectInput("Value 2", value2, randomBlock.max);
221
+ return randomBlock.output;
222
+ }
223
+ else {
224
+ // Single value
225
+ const sizeBlock = new ParticleInputBlock("Value");
226
+ sizeBlock.value = value1;
227
+ return sizeBlock.output;
228
+ }
123
229
  }
124
- function _CreateEmitterShapeBlock(oldSystem) {
230
+ // ------------- EMITTER SHAPE FUNCTIONS -------------
231
+ function _EmitterShapeBlock(oldSystem) {
125
232
  const emitter = oldSystem.particleEmitterType;
126
233
  if (!emitter) {
127
234
  throw new Error("Particle system has no emitter type.");
@@ -150,6 +257,19 @@ function _CreateEmitterShapeBlock(oldSystem) {
150
257
  _CreateAndConnectInput("Direction Randomizer", source.directionRandomizer, target.directionRandomizer);
151
258
  break;
152
259
  }
260
+ case "ConeDirectedParticleEmitter": {
261
+ const source = emitter;
262
+ shapeBlock = new ConeShapeBlock("Cone Shape");
263
+ const target = shapeBlock;
264
+ target.emitFromSpawnPointOnly = source.emitFromSpawnPointOnly;
265
+ _CreateAndConnectInput("Radius", source.radius, target.radius);
266
+ _CreateAndConnectInput("Angle", source.angle, target.angle);
267
+ _CreateAndConnectInput("Radius Range", source.radiusRange, target.radiusRange);
268
+ _CreateAndConnectInput("Height Range", source.heightRange, target.heightRange);
269
+ _CreateAndConnectInput("Direction 1", source.direction1, target.direction1);
270
+ _CreateAndConnectInput("Direction 2", source.direction2, target.direction2);
271
+ break;
272
+ }
153
273
  case "CustomParticleEmitter": {
154
274
  const source = emitter;
155
275
  shapeBlock = new CustomShapeBlock("Custom Shape");
@@ -233,36 +353,195 @@ function _CreateEmitterShapeBlock(oldSystem) {
233
353
  }
234
354
  return shapeBlock;
235
355
  }
236
- function _CreateUpdateSystem(inputParticle, oldSystem) {
237
- let outputUpdate = inputParticle;
238
- if (oldSystem.minAngularSpeed !== 0 || oldSystem.maxAngularSpeed !== 0) {
239
- outputUpdate = _CreateAngularSpeedUpdate(outputUpdate, oldSystem.minAngularSpeed, oldSystem.maxAngularSpeed);
356
+ // ------------- UPDATE PARTICLE FUNCTIONS -------------
357
+ /**
358
+ * Creates the group of blocks that represent the particle system update
359
+ * The creation of the different properties follows the order they are added to the ProcessQueue in ThinParticleSystem:
360
+ * Color, AngularSpeedGradients, AngularSpeed, VelocityGradients, Direction, LimitVelocityGradients, DragGradients, Position, Noise, SizeGradients, Gravity, RemapGradients
361
+ * @param inputParticle The particle input connection point
362
+ * @param oldSystem The old particle system to convert
363
+ * @param context The runtime conversion context
364
+ * @returns The output connection point after all updates have been applied
365
+ */
366
+ function _UpdateParticleBlockGroup(inputParticle, oldSystem, context) {
367
+ let updateBlockGroupOutput = inputParticle;
368
+ updateBlockGroupOutput = _UpdateParticleColorBlockGroup(updateBlockGroupOutput, oldSystem._colorGradients, context);
369
+ updateBlockGroupOutput = _UpdateParticleAngleBlockGroup(updateBlockGroupOutput, oldSystem, context);
370
+ if (oldSystem._velocityGradients && oldSystem._velocityGradients.length > 0) {
371
+ context.scaledDirection = _UpdateParticleVelocityGradientBlockGroup(oldSystem._velocityGradients, context);
372
+ }
373
+ if (oldSystem._dragGradients && oldSystem._dragGradients.length > 0) {
374
+ context.scaledDirection = _UpdateParticleDragGradientBlockGroup(oldSystem._dragGradients, context);
375
+ }
376
+ updateBlockGroupOutput = _UpdateParticlePositionBlockGroup(updateBlockGroupOutput, oldSystem.isLocal, context);
377
+ if (oldSystem._limitVelocityGradients && oldSystem._limitVelocityGradients.length > 0 && oldSystem.limitVelocityDamping !== 0) {
378
+ updateBlockGroupOutput = _UpdateParticleVelocityLimitGradientBlockGroup(updateBlockGroupOutput, oldSystem._limitVelocityGradients, oldSystem.limitVelocityDamping, context);
379
+ }
380
+ if (oldSystem._sizeGradients && oldSystem._sizeGradients.length > 0) {
381
+ updateBlockGroupOutput = _UpdateParticleSizeGradientBlockGroup(updateBlockGroupOutput, oldSystem._sizeGradients, context);
240
382
  }
241
- outputUpdate = _CreatePositionUpdate(outputUpdate, oldSystem.isLocal);
242
383
  if (oldSystem.gravity.equalsToFloats(0, 0, 0) === false) {
243
- outputUpdate = _CreateGravityUpdate(outputUpdate, oldSystem.gravity);
384
+ updateBlockGroupOutput = _UpdateParticleGravityBlockGroup(updateBlockGroupOutput, oldSystem.gravity);
244
385
  }
245
- return outputUpdate;
386
+ return updateBlockGroupOutput;
246
387
  }
247
- function _CreateAngularSpeedUpdate(inputParticle, minAngularSpeed, maxAngularSpeed) {
248
- // Random value between for the angular speed of the particle
249
- const randomAngularSpeedBlock = new ParticleRandomBlock("Random Angular Speed");
250
- _CreateAndConnectInput("Min Angular Speed", minAngularSpeed, randomAngularSpeedBlock.min);
251
- _CreateAndConnectInput("Max Angular Speed", maxAngularSpeed, randomAngularSpeedBlock.max);
252
- // Create the angular speed delta
253
- const angleSpeedDeltaOutput = _CreateDeltaModifiedInput("Angular Speed", randomAngularSpeedBlock.output);
254
- // Add it to the angle
255
- const addAngle = new ParticleMathBlock("Add Angular Speed to Angle");
256
- addAngle.operation = ParticleMathBlockOperations.Add;
257
- _CreateAndConnectContextualSource("Angle", NodeParticleContextualSources.Angle, addAngle.left);
258
- angleSpeedDeltaOutput.connectTo(addAngle.right);
259
- // Update the particle angle
260
- const updateAngle = new UpdateAngleBlock("Angle Update with Angular Speed");
261
- inputParticle.connectTo(updateAngle.particle);
262
- addAngle.output.connectTo(updateAngle.angle);
263
- return updateAngle.output;
264
- }
265
- function _CreatePositionUpdate(inputParticle, isLocal) {
388
+ /**
389
+ * Creates the group of blocks that represent the particle color update
390
+ * @param inputParticle The input particle to update
391
+ * @param colorGradients The color gradients (if any)
392
+ * @param context The context of the current conversion
393
+ * @returns The output of the group of blocks that represent the particle color update
394
+ */
395
+ function _UpdateParticleColorBlockGroup(inputParticle, colorGradients, context) {
396
+ let colorCalculation = undefined;
397
+ if (colorGradients && colorGradients.length > 0) {
398
+ if (context.colorGradientValue0Output === undefined) {
399
+ throw new Error("Initial color gradient values not found in context.");
400
+ }
401
+ context.ageToLifeTimeRatioBlockGroupOutput = _CreateAgeToLifeTimeRatioBlockGroup(context);
402
+ colorCalculation = _CreateGradientBlockGroup(context.ageToLifeTimeRatioBlockGroupOutput, colorGradients, ParticleRandomBlockLocks.OncePerParticle, "Color", [
403
+ context.colorGradientValue0Output,
404
+ ]);
405
+ }
406
+ else {
407
+ colorCalculation = _BasicColorUpdateBlockGroup();
408
+ }
409
+ // Create the color update block clamping alpha >= 0
410
+ const colorUpdateBlock = new UpdateColorBlock("Color update");
411
+ inputParticle.connectTo(colorUpdateBlock.particle);
412
+ _ClampUpdateColorAlpha(colorCalculation).connectTo(colorUpdateBlock.color);
413
+ return colorUpdateBlock.output;
414
+ }
415
+ /**
416
+ * Creates the group of blocks that represent the particle angle update
417
+ * @param inputParticle The input particle to update
418
+ * @param oldSystem The old particle system to convert
419
+ * @param context The context of the current conversion
420
+ * @returns The output of the group of blocks that represent the particle color update
421
+ */
422
+ function _UpdateParticleAngleBlockGroup(inputParticle, oldSystem, context) {
423
+ // We will try to use gradients if they exist
424
+ // If not, we will try to use min/max angular speed
425
+ let angularSpeedCalculation = null;
426
+ if (oldSystem._angularSpeedGradients && oldSystem._angularSpeedGradients.length > 0) {
427
+ angularSpeedCalculation = _UpdateParticleAngularSpeedGradientBlockGroup(oldSystem._angularSpeedGradients, context);
428
+ }
429
+ else if (oldSystem.minAngularSpeed !== 0 || oldSystem.maxAngularSpeed !== 0) {
430
+ angularSpeedCalculation = _UpdateParticleAngularSpeedBlockGroup(oldSystem.minAngularSpeed, oldSystem.maxAngularSpeed);
431
+ }
432
+ // If we have an angular speed calculation, then update the angle
433
+ if (angularSpeedCalculation) {
434
+ // Create the angular speed delta
435
+ const angleSpeedDeltaOutput = _CreateDeltaModifiedInput("Angular Speed", angularSpeedCalculation);
436
+ // Add it to the angle
437
+ const addAngle = new ParticleMathBlock("Add Angular Speed to Angle");
438
+ addAngle.operation = ParticleMathBlockOperations.Add;
439
+ _CreateAndConnectContextualSource("Angle", NodeParticleContextualSources.Angle, addAngle.left);
440
+ angleSpeedDeltaOutput.connectTo(addAngle.right);
441
+ // Update the particle angle
442
+ const updateAngle = new UpdateAngleBlock("Angle Update with Angular Speed");
443
+ inputParticle.connectTo(updateAngle.particle);
444
+ addAngle.output.connectTo(updateAngle.angle);
445
+ return updateAngle.output;
446
+ }
447
+ else {
448
+ return inputParticle;
449
+ }
450
+ }
451
+ /**
452
+ * Creates the group of blocks that represent the particle velocity update
453
+ * @param velocityGradients The velocity gradients
454
+ * @param context The context of the current conversion
455
+ * @returns The output of the group of blocks that represent the particle velocity update
456
+ */
457
+ function _UpdateParticleVelocityGradientBlockGroup(velocityGradients, context) {
458
+ context.ageToLifeTimeRatioBlockGroupOutput = _CreateAgeToLifeTimeRatioBlockGroup(context);
459
+ // Generate the gradient
460
+ const velocityValueOutput = _CreateGradientBlockGroup(context.ageToLifeTimeRatioBlockGroupOutput, velocityGradients, ParticleRandomBlockLocks.OncePerParticle, "Velocity");
461
+ // Update the direction scale based on the velocity
462
+ const multiplyScaleByVelocity = new ParticleMathBlock("Multiply Direction Scale by Velocity");
463
+ multiplyScaleByVelocity.operation = ParticleMathBlockOperations.Multiply;
464
+ velocityValueOutput.connectTo(multiplyScaleByVelocity.left);
465
+ _CreateAndConnectContextualSource("Direction Scale", NodeParticleContextualSources.DirectionScale, multiplyScaleByVelocity.right);
466
+ // Update the particle direction scale
467
+ const multiplyDirection = new ParticleMathBlock("Scaled Direction");
468
+ multiplyDirection.operation = ParticleMathBlockOperations.Multiply;
469
+ multiplyScaleByVelocity.output.connectTo(multiplyDirection.left);
470
+ _CreateAndConnectContextualSource("Direction", NodeParticleContextualSources.Direction, multiplyDirection.right);
471
+ // Store the new calculation of the scaled direction in the context
472
+ context.scaledDirection = multiplyDirection.output;
473
+ return multiplyDirection.output;
474
+ }
475
+ /**
476
+ * Creates the group of blocks that represent the particle velocity limit update
477
+ * @param inputParticle The input particle to update
478
+ * @param velocityLimitGradients The velocity limit gradients
479
+ * @param limitVelocityDamping The limit velocity damping factor
480
+ * @param context The context of the current conversion
481
+ * @returns The output of the group of blocks that represent the particle velocity limit update
482
+ */
483
+ function _UpdateParticleVelocityLimitGradientBlockGroup(inputParticle, velocityLimitGradients, limitVelocityDamping, context) {
484
+ context.ageToLifeTimeRatioBlockGroupOutput = _CreateAgeToLifeTimeRatioBlockGroup(context);
485
+ // Calculate the current speed
486
+ const currentSpeedBlock = new ParticleVectorLengthBlock("Current Speed");
487
+ _CreateAndConnectContextualSource("Direction", NodeParticleContextualSources.Direction, currentSpeedBlock.input);
488
+ // Calculate the velocity limit from the gradient
489
+ const velocityLimitValueOutput = _CreateGradientBlockGroup(context.ageToLifeTimeRatioBlockGroupOutput, velocityLimitGradients, ParticleRandomBlockLocks.OncePerParticle, "Velocity Limit");
490
+ // Blocks that will calculate the new velocity if over the limit
491
+ const damped = new ParticleMathBlock("Damped Speed");
492
+ damped.operation = ParticleMathBlockOperations.Multiply;
493
+ _CreateAndConnectContextualSource("Direction", NodeParticleContextualSources.Direction, damped.left);
494
+ _CreateAndConnectInput("Limit Velocity Damping", limitVelocityDamping, damped.right);
495
+ // Compare current speed and limit
496
+ const compareSpeed = new ParticleConditionBlock("Compare Speed to Limit");
497
+ compareSpeed.test = ParticleConditionBlockTests.GreaterThan;
498
+ currentSpeedBlock.output.connectTo(compareSpeed.left);
499
+ velocityLimitValueOutput.connectTo(compareSpeed.right);
500
+ damped.output.connectTo(compareSpeed.ifTrue);
501
+ _CreateAndConnectContextualSource("Direction", NodeParticleContextualSources.Direction, compareSpeed.ifFalse);
502
+ // Update the direction based on the calculted value
503
+ const updateDirection = new UpdateDirectionBlock("Direction Update");
504
+ inputParticle.connectTo(updateDirection.particle);
505
+ compareSpeed.output.connectTo(updateDirection.direction);
506
+ return updateDirection.output;
507
+ }
508
+ /**
509
+ * Creates the group of blocks that represent the particle drag update
510
+ * @param dragGradients The drag gradients
511
+ * @param context The context of the current conversion
512
+ * @returns The output of the group of blocks that represent the particle drag update
513
+ */
514
+ function _UpdateParticleDragGradientBlockGroup(dragGradients, context) {
515
+ context.ageToLifeTimeRatioBlockGroupOutput = _CreateAgeToLifeTimeRatioBlockGroup(context);
516
+ // Generate the gradient
517
+ const dragValueOutput = _CreateGradientBlockGroup(context.ageToLifeTimeRatioBlockGroupOutput, dragGradients, ParticleRandomBlockLocks.OncePerParticle, "Drag");
518
+ // Calculate drag factor
519
+ const oneMinusDragBlock = new ParticleMathBlock("1 - Drag");
520
+ oneMinusDragBlock.operation = ParticleMathBlockOperations.Subtract;
521
+ _CreateAndConnectInput("One", 1, oneMinusDragBlock.left);
522
+ dragValueOutput.connectTo(oneMinusDragBlock.right);
523
+ // Multiply the scaled direction by drag factor
524
+ const multiplyDirection = new ParticleMathBlock("Scaled Direction with Drag");
525
+ multiplyDirection.operation = ParticleMathBlockOperations.Multiply;
526
+ oneMinusDragBlock.output.connectTo(multiplyDirection.left);
527
+ if (context.scaledDirection === undefined) {
528
+ _CreateAndConnectContextualSource("Scaled Direction", NodeParticleContextualSources.ScaledDirection, multiplyDirection.right);
529
+ }
530
+ else {
531
+ context.scaledDirection.connectTo(multiplyDirection.right);
532
+ }
533
+ // Store the new calculation of the scaled direction in the context
534
+ context.scaledDirection = multiplyDirection.output;
535
+ return multiplyDirection.output;
536
+ }
537
+ /**
538
+ * Creates the group of blocks that represent the particle position update
539
+ * @param inputParticle The input particle to update
540
+ * @param isLocal Whether the particle coordinate system is local or not
541
+ * @param context The context of the current conversion
542
+ * @returns The output of the group of blocks that represent the particle position update
543
+ */
544
+ function _UpdateParticlePositionBlockGroup(inputParticle, isLocal, context) {
266
545
  // Update the particle position
267
546
  const updatePosition = new UpdatePositionBlock("Position Update");
268
547
  inputParticle.connectTo(updatePosition.particle);
@@ -274,12 +553,45 @@ function _CreatePositionUpdate(inputParticle, isLocal) {
274
553
  const addPositionBlock = new ParticleMathBlock("Add Position");
275
554
  addPositionBlock.operation = ParticleMathBlockOperations.Add;
276
555
  _CreateAndConnectContextualSource("Position", NodeParticleContextualSources.Position, addPositionBlock.left);
277
- _CreateAndConnectContextualSource("Scaled Direction", NodeParticleContextualSources.ScaledDirection, addPositionBlock.right);
556
+ if (context.scaledDirection === undefined) {
557
+ _CreateAndConnectContextualSource("Scaled Direction", NodeParticleContextualSources.ScaledDirection, addPositionBlock.right);
558
+ }
559
+ else {
560
+ context.scaledDirection.connectTo(addPositionBlock.right);
561
+ }
278
562
  addPositionBlock.output.connectTo(updatePosition.position);
279
563
  }
280
564
  return updatePosition.output;
281
565
  }
282
- function _CreateGravityUpdate(inputParticle, gravity) {
566
+ /**
567
+ * Creates the group of blocks that represent the particle size update
568
+ * @param inputParticle The input particle to update
569
+ * @param sizeGradients The size gradients (if any)
570
+ * @param context The context of the current conversion
571
+ * @returns The output of the group of blocks that represent the particle size update
572
+ */
573
+ function _UpdateParticleSizeGradientBlockGroup(inputParticle, sizeGradients, context) {
574
+ if (context.sizeGradientValue0Output === undefined) {
575
+ throw new Error("Initial size gradient values not found in context.");
576
+ }
577
+ context.ageToLifeTimeRatioBlockGroupOutput = _CreateAgeToLifeTimeRatioBlockGroup(context);
578
+ // Generate the gradient
579
+ const sizeValueOutput = _CreateGradientBlockGroup(context.ageToLifeTimeRatioBlockGroupOutput, sizeGradients, ParticleRandomBlockLocks.OncePerParticle, "Size", [
580
+ context.sizeGradientValue0Output,
581
+ ]);
582
+ // Create the update size
583
+ const updateSizeBlock = new UpdateSizeBlock("Size Update");
584
+ inputParticle.connectTo(updateSizeBlock.particle);
585
+ sizeValueOutput.connectTo(updateSizeBlock.size);
586
+ return updateSizeBlock.output;
587
+ }
588
+ /**
589
+ * Creates the group of blocks that represent the particle gravity update
590
+ * @param inputParticle The input particle to update
591
+ * @param gravity The gravity vector to apply
592
+ * @returns The output of the group of blocks that represent the particle gravity update
593
+ */
594
+ function _UpdateParticleGravityBlockGroup(inputParticle, gravity) {
283
595
  // Create the gravity delta
284
596
  const gravityDeltaOutput = _CreateDeltaModifiedInput("Gravity", gravity);
285
597
  // Add it to the direction
@@ -293,90 +605,31 @@ function _CreateGravityUpdate(inputParticle, gravity) {
293
605
  addDirectionBlock.output.connectTo(updateDirection.direction);
294
606
  return updateDirection.output;
295
607
  }
296
- function _CreateColorUpdateBlock(oldSystem, createParticleBlock) {
297
- if (!oldSystem) {
298
- throw new Error("Invalid particle system");
299
- }
300
- // Calculate the color
301
- const colorGradients = oldSystem.getColorGradients();
302
- let colorBlock = null;
303
- if (colorGradients && colorGradients.length > 0) {
304
- colorBlock = _CreateGradientColorUpdate(oldSystem, colorGradients, createParticleBlock);
305
- }
306
- else {
307
- colorBlock = _CreateBasicColorUpdate(oldSystem, createParticleBlock);
308
- }
309
- // Clamp alpha >= 0
310
- const clampedColor = _ClampUpdateColorAlpha(colorBlock);
311
- // Create the color update block
312
- const colorUpdateBlock = new UpdateColorBlock("Color update");
313
- clampedColor.colorOut.connectTo(colorUpdateBlock.color);
314
- return colorUpdateBlock;
315
- }
316
- function _CreateGradientColorUpdate(oldSystem, gradient, createParticleBlock) {
317
- const colorGradientBlock = new ParticleGradientBlock("Color Gradient");
318
- _CreateAndConnectContextualSource("gradient", NodeParticleContextualSources.Age, colorGradientBlock.gradient);
319
- let tempColor = null;
320
- let colorStart = null;
321
- let colorEnd = null;
322
- for (let i = 0; i < gradient.length; i++) {
323
- const gradientStep = gradient[i];
324
- const gradientValueBlock = new ParticleGradientValueBlock("Color Gradient Value " + i);
325
- gradientValueBlock.reference = gradientStep.gradient;
326
- if (gradientStep.color2) {
327
- // Create a random between color1 and color2
328
- const randomColorBlock = new ParticleRandomBlock("Random Color for Gradient " + i);
329
- randomColorBlock.lockMode = ParticleRandomBlockLocks.PerSystem;
330
- _CreateAndConnectInput("Color 1", gradientStep.color1, randomColorBlock.min);
331
- _CreateAndConnectInput("Color 2", gradientStep.color2, randomColorBlock.max);
332
- randomColorBlock.output.connectTo(gradientValueBlock.value);
333
- tempColor = randomColorBlock;
334
- }
335
- else {
336
- // Single color
337
- const input = new ParticleInputBlock("Color " + i);
338
- input.value = gradientStep.color1;
339
- input.output.connectTo(gradientValueBlock.value);
340
- tempColor = input;
341
- }
342
- if (gradientStep.gradient === 0) {
343
- colorStart = tempColor;
344
- }
345
- else if (gradientStep.gradient === 1) {
346
- colorEnd = tempColor;
347
- }
348
- gradientValueBlock.output.connectTo(colorGradientBlock.inputs[i + 1]);
349
- }
350
- _UpdateCreateParticleColor(oldSystem, colorStart, colorEnd, createParticleBlock);
351
- return colorGradientBlock;
608
+ function _UpdateParticleAngularSpeedGradientBlockGroup(angularSpeedGradients, context) {
609
+ context.ageToLifeTimeRatioBlockGroupOutput = _CreateAgeToLifeTimeRatioBlockGroup(context);
610
+ // Generate the gradient
611
+ const angularSpeedValueOutput = _CreateGradientBlockGroup(context.ageToLifeTimeRatioBlockGroupOutput, angularSpeedGradients, ParticleRandomBlockLocks.OncePerParticle, "Angular Speed");
612
+ return angularSpeedValueOutput;
352
613
  }
353
- function _CreateBasicColorUpdate(oldSystem, createParticleBlock) {
614
+ function _UpdateParticleAngularSpeedBlockGroup(minAngularSpeed, maxAngularSpeed) {
615
+ // Random value between for the angular speed of the particle
616
+ const randomAngularSpeedBlock = new ParticleRandomBlock("Random Angular Speed");
617
+ randomAngularSpeedBlock.lockMode = ParticleRandomBlockLocks.OncePerParticle;
618
+ _CreateAndConnectInput("Min Angular Speed", minAngularSpeed, randomAngularSpeedBlock.min);
619
+ _CreateAndConnectInput("Max Angular Speed", maxAngularSpeed, randomAngularSpeedBlock.max);
620
+ return randomAngularSpeedBlock.output;
621
+ }
622
+ function _BasicColorUpdateBlockGroup() {
354
623
  const addColorBlock = new ParticleMathBlock("Add Color");
355
624
  addColorBlock.operation = ParticleMathBlockOperations.Add;
356
625
  _CreateAndConnectContextualSource("Color", NodeParticleContextualSources.Color, addColorBlock.left);
357
626
  _CreateAndConnectContextualSource("Scaled Color Step", NodeParticleContextualSources.ScaledColorStep, addColorBlock.right);
358
- _UpdateCreateParticleColor(oldSystem, null, null, createParticleBlock);
359
- return addColorBlock;
627
+ return addColorBlock.output;
360
628
  }
361
- function _UpdateCreateParticleColor(oldSystem, colorStart, colorEnd, createParticleBlock) {
362
- if (colorStart === null) {
363
- colorStart = new ParticleInputBlock("Color Start");
364
- colorStart.value = oldSystem.color1;
365
- }
366
- if (colorEnd === null) {
367
- colorEnd = new ParticleInputBlock("Color End");
368
- colorEnd.value = oldSystem.color2;
369
- }
370
- const randomColorBlock = new ParticleRandomBlock("Random color");
371
- randomColorBlock.lockMode = ParticleRandomBlockLocks.PerParticle;
372
- colorStart.output.connectTo(randomColorBlock.min);
373
- colorEnd.output.connectTo(randomColorBlock.max);
374
- randomColorBlock.output.connectTo(createParticleBlock.color);
375
- }
376
- function _ClampUpdateColorAlpha(colorBlock) {
629
+ function _ClampUpdateColorAlpha(colorCalculationOutput) {
377
630
  // Decompose color to clamp alpha
378
631
  const decomposeColorBlock = new ParticleConverterBlock("Decompose Color");
379
- colorBlock.outputs[0].connectTo(decomposeColorBlock.colorIn);
632
+ colorCalculationOutput.connectTo(decomposeColorBlock.colorIn);
380
633
  // Clamp alpha to be >= 0
381
634
  const maxAlphaBlock = new ParticleMathBlock("Alpha >= 0");
382
635
  maxAlphaBlock.operation = ParticleMathBlockOperations.Max;
@@ -386,8 +639,9 @@ function _ClampUpdateColorAlpha(colorBlock) {
386
639
  const composeColorBlock = new ParticleConverterBlock("Compose Color");
387
640
  decomposeColorBlock.xyzOut.connectTo(composeColorBlock.xyzIn);
388
641
  maxAlphaBlock.output.connectTo(composeColorBlock.wIn);
389
- return composeColorBlock;
642
+ return composeColorBlock.colorOut;
390
643
  }
644
+ // ------------- UTILITY FUNCTIONS -------------
391
645
  function _CreateDeltaModifiedInput(name, value) {
392
646
  const multiplyBlock = new ParticleMathBlock("Multiply by Delta");
393
647
  multiplyBlock.operation = ParticleMathBlockOperations.Multiply;
@@ -415,4 +669,127 @@ function _CreateAndConnectSystemSource(systemBlockName, systemSource, targetToCo
415
669
  input.systemSource = systemSource;
416
670
  input.output.connectTo(targetToConnectTo);
417
671
  }
672
+ /**
673
+ * Creates the target stop duration input block, as it can be shared in multiple places
674
+ * This block is stored in the context so the same block is shared in the graph
675
+ * @param oldSystem The old particle system to convert
676
+ * @param context The context of the current conversion
677
+ * @returns
678
+ */
679
+ function _CreateTargetStopDurationInputBlock(oldSystem, context) {
680
+ // If we have already created the target stop duration input block, return it
681
+ if (context.targetStopDurationBlockOutput) {
682
+ return context.targetStopDurationBlockOutput;
683
+ }
684
+ // Create the target stop duration input block if not already created
685
+ const targetStopDurationInputBlock = new ParticleInputBlock("Target Stop Duration");
686
+ targetStopDurationInputBlock.value = oldSystem.targetStopDuration;
687
+ // Save the output in our context to avoid regenerating it again
688
+ context.targetStopDurationBlockOutput = targetStopDurationInputBlock.output;
689
+ return context.targetStopDurationBlockOutput;
690
+ }
691
+ /**
692
+ * Create a group of blocks that calculates the ratio between the actual frame and the target stop duration, clamped between 0 and 1.
693
+ * This is used to simulate the behavior of the old particle system where several particle gradient values are affected by the target stop duration.
694
+ * This block group is stored in the context so the same group is shared in the graph
695
+ * @param oldSystem The old particle system to convert
696
+ * @param context The context of the current conversion
697
+ * @returns The ratio block output connection point
698
+ */
699
+ function _CreateTimeToStopTimeRatioBlockGroup(oldSystem, context) {
700
+ // If we have already generated this group, return it
701
+ if (context.timeToStopTimeRatioBlockGroupOutput) {
702
+ return context.timeToStopTimeRatioBlockGroupOutput;
703
+ }
704
+ context.targetStopDurationBlockOutput = _CreateTargetStopDurationInputBlock(oldSystem, context);
705
+ // Find the ratio between the actual frame and the target stop duration
706
+ const ratio = new ParticleMathBlock("Frame/Stop Ratio");
707
+ ratio.operation = ParticleMathBlockOperations.Divide;
708
+ _CreateAndConnectSystemSource("Actual Frame", NodeParticleSystemSources.Time, ratio.left);
709
+ context.targetStopDurationBlockOutput.connectTo(ratio.right);
710
+ // Make sure values is >=0
711
+ const clampMin = new ParticleMathBlock("Clamp Min 0");
712
+ clampMin.operation = ParticleMathBlockOperations.Max;
713
+ _CreateAndConnectInput("Zero", 0, clampMin.left);
714
+ ratio.output.connectTo(clampMin.right);
715
+ // Make sure values is <=1
716
+ const clampMax = new ParticleMathBlock("Clamp Max 1");
717
+ clampMax.operation = ParticleMathBlockOperations.Min;
718
+ _CreateAndConnectInput("One", 1, clampMax.left);
719
+ clampMin.output.connectTo(clampMax.right);
720
+ // Save the group output in our context to avoid regenerating it again
721
+ context.timeToStopTimeRatioBlockGroupOutput = clampMax.output;
722
+ return context.timeToStopTimeRatioBlockGroupOutput;
723
+ }
724
+ function _CreateAgeToLifeTimeRatioBlockGroup(context) {
725
+ // If we have already generated this group, return it
726
+ if (context.ageToLifeTimeRatioBlockGroupOutput) {
727
+ return context.ageToLifeTimeRatioBlockGroupOutput;
728
+ }
729
+ // Find the ratio between the age and the lifetime
730
+ const ratio = new ParticleMathBlock("Age/LifeTime Ratio");
731
+ ratio.operation = ParticleMathBlockOperations.Divide;
732
+ _CreateAndConnectContextualSource("Age", NodeParticleContextualSources.Age, ratio.left);
733
+ _CreateAndConnectContextualSource("LifeTime", NodeParticleContextualSources.Lifetime, ratio.right);
734
+ // Save the group output in our context to avoid regenerating it again
735
+ context.ageToLifeTimeRatioBlockGroupOutput = ratio.output;
736
+ return ratio.output;
737
+ }
738
+ /**
739
+ * Creates the blocks that represent a gradient
740
+ * @param gradientSelector The value that determines which gradient to use
741
+ * @param gradientValues The list of gradient values
742
+ * @param randomLockMode The type of random to use for the gradient values
743
+ * @param prefix The prefix to use for naming the blocks
744
+ * @param initialValues Optional initial values to connect to the gradient inputs that were calculated during other steps of the conversion
745
+ * @returns The output connection point of the gradient block
746
+ */
747
+ function _CreateGradientBlockGroup(gradientSelector, gradientValues, randomLockMode, prefix, initialValues = []) {
748
+ // Create the gradient block and connect the value that controls the gradient selection
749
+ const gradientBlock = new ParticleGradientBlock(prefix + " Gradient Block");
750
+ gradientSelector.connectTo(gradientBlock.gradient);
751
+ // If initial values are provided, we use them instead of the values in the gradientValues array
752
+ // These means this values were already transformed into blocks on a previous step of the conversion and we must reuse them
753
+ for (let i = 0; i < initialValues.length; i++) {
754
+ const reference = i < gradientValues.length ? gradientValues[i].gradient : 1;
755
+ const gradientValueBlock = new ParticleGradientValueBlock(prefix + " Gradient Value " + i);
756
+ gradientValueBlock.reference = reference;
757
+ initialValues[i].connectTo(gradientValueBlock.value);
758
+ gradientValueBlock.output.connectTo(gradientBlock.inputs[i + 1]);
759
+ }
760
+ // Create the gradient values
761
+ for (let i = 0 + initialValues.length; i < gradientValues.length; i++) {
762
+ const gradientValueBlockGroupOutput = _CreateGradientValueBlockGroup(gradientValues[i], randomLockMode, prefix, i);
763
+ gradientValueBlockGroupOutput.connectTo(gradientBlock.inputs[i + 1]);
764
+ }
765
+ return gradientBlock.output;
766
+ }
767
+ /**
768
+ * Creates the blocks that represent a gradient value
769
+ * This can be either a single value or a random between two values
770
+ * @param gradientStep The gradient step data
771
+ * @param randomLockMode The lock mode to use for random values
772
+ * @param prefix The prefix to use for naming the blocks
773
+ * @param index The index of the gradient step
774
+ * @returns The output connection point of the gradient value block
775
+ */
776
+ function _CreateGradientValueBlockGroup(gradientStep, randomLockMode, prefix, index) {
777
+ const gradientValueBlock = new ParticleGradientValueBlock(prefix + " Gradient Value " + index);
778
+ gradientValueBlock.reference = gradientStep.gradient;
779
+ const value1 = gradientStep.factor1 ?? gradientStep.color1;
780
+ const value2 = gradientStep.factor2 ?? gradientStep.color2;
781
+ if (value2 !== undefined) {
782
+ // Create a random between value1 and value2
783
+ const randomBlock = new ParticleRandomBlock("Random Value " + index);
784
+ randomBlock.lockMode = randomLockMode;
785
+ _CreateAndConnectInput("Value 1", value1, randomBlock.min);
786
+ _CreateAndConnectInput("Value 2", value2, randomBlock.max);
787
+ randomBlock.output.connectTo(gradientValueBlock.value);
788
+ }
789
+ else {
790
+ // Single value
791
+ _CreateAndConnectInput("Value", value1, gradientValueBlock.value);
792
+ }
793
+ return gradientValueBlock.output;
794
+ }
418
795
  //# sourceMappingURL=nodeParticleSystemSet.helper.js.map