Skip to content
Draft
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
4629a7d
Add Solid Particle System (SPS) blocks to Node Particle Editor
Oct 10, 2025
c5d8db6
Enhance Node Particle System with Solid Particle Blocks
Oct 14, 2025
fc2df4b
Refactor Solid Particle System initialization and cleanup
Oct 14, 2025
0be8117
Update NodeParticleEditor to use setToDefault method for NodeParticle…
Oct 14, 2025
6d72319
Enhance Solid Particle System with isStarted flag and update NodePart…
Oct 17, 2025
5a6e5b9
Enhance NodeParticleConnectionPoint to support multiple connections
Oct 17, 2025
b31248e
Refactor Solid Particle System and Node Particle Editor for improved …
Oct 20, 2025
3f7d61f
Refactor SPSSystemBlock to streamline particle initialization and upd…
Oct 20, 2025
7539783
Enhance SolidParticleSystem and NodeParticleSystemSet with improved d…
Oct 20, 2025
4ff96c9
Refactor NodeParticleBlock and NodeParticleConnectionPoint to simplif…
Oct 21, 2025
2d7e11c
Add unregisterInput method to NodeParticleBlock for dynamic input man…
Oct 21, 2025
396662b
Remove optional `allowMultipleConnections` property from IPortData in…
Oct 21, 2025
72c885b
Refactor SolidParticleSystem and related blocks for improved initiali…
Oct 28, 2025
014681f
Refactor SolidParticleSystem blocks to introduce SPSParticleConfigBlo…
Oct 29, 2025
9c25aa6
Refactor SPSCreateBlock and SPSSystemBlock to improve lifecycle manag…
Oct 30, 2025
6da7359
Enhance ParticleSystemSet to support SolidParticleSystem integration
Oct 31, 2025
e37f61f
Enhance NodeParticleBuildState and NodeParticleSystemSet for SolidPar…
Nov 14, 2025
dc4db46
Refactor SPSInitBlock and SPSUpdateBlock to streamline value retrieval
Nov 14, 2025
d116da5
Refactor NodeParticleSystemSet to streamline random position and rota…
Nov 14, 2025
69a803a
Remove commented-out steps in NodeParticleSystemSet for improved code…
Nov 14, 2025
50115b2
Add ParticlePropsSetBlock and ParticlePropsGetBlock for dynamic prope…
Nov 14, 2025
3289658
Enhance particle property management with String type support and dis…
Nov 14, 2025
8833c50
Add Solid Particle System (SPS) blocks to Node Particle Editor
Oct 10, 2025
3430d2f
Enhance Node Particle System with Solid Particle Blocks
Oct 14, 2025
be2185e
Refactor Solid Particle System initialization and cleanup
Oct 14, 2025
5b797bc
Update NodeParticleEditor to use setToDefault method for NodeParticle…
Oct 14, 2025
b63f06e
Enhance Solid Particle System with isStarted flag and update NodePart…
Oct 17, 2025
5ee2820
Enhance NodeParticleConnectionPoint to support multiple connections
Oct 17, 2025
1617792
Refactor Solid Particle System and Node Particle Editor for improved …
Oct 20, 2025
5dc1e1d
Refactor SPSSystemBlock to streamline particle initialization and upd…
Oct 20, 2025
eaeecf4
Enhance SolidParticleSystem and NodeParticleSystemSet with improved d…
Oct 20, 2025
4994414
Refactor NodeParticleBlock and NodeParticleConnectionPoint to simplif…
Oct 21, 2025
140a45e
Add unregisterInput method to NodeParticleBlock for dynamic input man…
Oct 21, 2025
62c7143
Remove optional `allowMultipleConnections` property from IPortData in…
Oct 21, 2025
9791892
Refactor SolidParticleSystem and related blocks for improved initiali…
Oct 28, 2025
dfe540f
Refactor SolidParticleSystem blocks to introduce SPSParticleConfigBlo…
Oct 29, 2025
a4207e3
Refactor SPSCreateBlock and SPSSystemBlock to improve lifecycle manag…
Oct 30, 2025
6ac1d15
Enhance ParticleSystemSet to support SolidParticleSystem integration
Oct 31, 2025
cc9bbe0
Enhance NodeParticleBuildState and NodeParticleSystemSet for SolidPar…
Nov 14, 2025
1eb3110
Refactor SPSInitBlock and SPSUpdateBlock to streamline value retrieval
Nov 14, 2025
b9a365b
Refactor NodeParticleSystemSet to streamline random position and rota…
Nov 14, 2025
bf82fdc
Remove commented-out steps in NodeParticleSystemSet for improved code…
Nov 14, 2025
2085aa6
Add ParticlePropsSetBlock and ParticlePropsGetBlock for dynamic prope…
Nov 14, 2025
c0c3d1d
Enhance particle property management with String type support and dis…
Nov 14, 2025
da65fb7
Merge branch 'feat/solid-particles-to-node-particle-editor' of https:…
Nov 14, 2025
e03fa4b
Remove String property from PropertyTypeForEdition enum and refactor …
Nov 14, 2025
499386d
Refactor particle property blocks to enhance naming consistency and t…
Nov 17, 2025
c3bf211
Merge remote-tracking branch 'upstream/master'
Nov 17, 2025
c3fa640
Merge branch 'master' into feat/solid-particles-to-node-particle-editor
Nov 17, 2025
28912f4
Implement SPSParticlePropsSetBlock and SPSParticlePropsGetBlock for d…
Nov 17, 2025
98d1dec
Add lifetime and disposeOnEnd properties to SPSSystemBlock and SolidP…
Nov 20, 2025
a0c36ab
Enhance particle system functionality with new mesh and material blocks
Nov 21, 2025
e1d549e
Refactor and enhance Solid Particle System blocks for improved functi…
Nov 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Vector3 } from "core/Maths/math.vector";

Check failure on line 1 in packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts

View check run for this annotation

Azure Pipelines / CI-Monorepo (Format, Lint, and more)

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts#L1

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts(1,1): error @typescript-eslint/consistent-type-imports: All imports in the declaration are only used as types. Use `import type`.

Check failure on line 1 in packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts

View check run for this annotation

Azure Pipelines / CI-Monorepo

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts#L1

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts(1,1): error @typescript-eslint/consistent-type-imports: All imports in the declaration are only used as types. Use `import type`.
import { Color4 } from "core/Maths/math.color";

Check failure on line 2 in packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts

View check run for this annotation

Azure Pipelines / CI-Monorepo (Format, Lint, and more)

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts#L2

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts(2,1): error @typescript-eslint/consistent-type-imports: All imports in the declaration are only used as types. Use `import type`.

Check failure on line 2 in packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts

View check run for this annotation

Azure Pipelines / CI-Monorepo

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts#L2

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts(2,1): error @typescript-eslint/consistent-type-imports: All imports in the declaration are only used as types. Use `import type`.
import type { Mesh } from "core/Meshes/mesh";
import type { Material } from "core/Materials/material";

/**
* Interface for SPS update block data
*/
export interface ISPSUpdateData {

Check failure on line 9 in packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts

View check run for this annotation

Azure Pipelines / CI-Monorepo (Format, Lint, and more)

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts#L9

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts(9,18): error @typescript-eslint/naming-convention: Interface name `ISPSUpdateData` trimmed as `SPSUpdateData` must match one of the following formats: StrictPascalCase

Check failure on line 9 in packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts

View check run for this annotation

Azure Pipelines / CI-Monorepo

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts#L9

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts(9,18): error @typescript-eslint/naming-convention: Interface name `ISPSUpdateData` trimmed as `SPSUpdateData` must match one of the following formats: StrictPascalCase
position: () => Vector3;
velocity: () => Vector3;
color: () => Color4;
scaling: () => Vector3;
rotation: () => Vector3;
}

/**
* Interface for SPS create block data
*/
export interface ISPSCreateData {

Check failure on line 20 in packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts

View check run for this annotation

Azure Pipelines / CI-Monorepo (Format, Lint, and more)

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts#L20

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts(20,18): error @typescript-eslint/naming-convention: Interface name `ISPSCreateData` trimmed as `SPSCreateData` must match one of the following formats: StrictPascalCase

Check failure on line 20 in packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts

View check run for this annotation

Azure Pipelines / CI-Monorepo

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts#L20

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/ISPSData.ts(20,18): error @typescript-eslint/naming-convention: Interface name `ISPSCreateData` trimmed as `SPSCreateData` must match one of the following formats: StrictPascalCase
mesh: Mesh;
count: number;
material?: Material;
initBlock?: ISPSUpdateData;
updateBlock?: ISPSUpdateData;
shapeId?: number;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { RegisterClass } from "../../../../Misc/typeStore";
import { NodeParticleBlockConnectionPointTypes } from "../../Enums/nodeParticleBlockConnectionPointTypes";
import { NodeParticleBlock } from "../../nodeParticleBlock";
import type { NodeParticleConnectionPoint } from "../../nodeParticleBlockConnectionPoint";
import type { NodeParticleBuildState } from "../../nodeParticleBuildState";
import type { ISPSCreateData } from "./ISPSData";

/**
* Block used to configure SPS parameters (mesh, count, initBlocks)
*/
export class SPSCreateBlock extends NodeParticleBlock {

Check failure on line 11 in packages/dev/core/src/Particles/Node/Blocks/SolidParticle/SPSCreateBlock.ts

View check run for this annotation

Azure Pipelines / CI-Monorepo (Format, Lint, and more)

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/SPSCreateBlock.ts#L11

packages/dev/core/src/Particles/Node/Blocks/SolidParticle/SPSCreateBlock.ts(11,14): error @typescript-eslint/naming-convention: Class name `SPSCreateBlock` must match one of the following formats: StrictPascalCase
public constructor(name: string) {
super(name);

this.registerInput("mesh", NodeParticleBlockConnectionPointTypes.Mesh);
this.registerInput("count", NodeParticleBlockConnectionPointTypes.Int, true, 1);
this.registerInput("material", NodeParticleBlockConnectionPointTypes.Material, true);
this.registerInput("initBlock", NodeParticleBlockConnectionPointTypes.System, true);
this.registerInput("updateBlock", NodeParticleBlockConnectionPointTypes.System, true);

this.registerOutput("solidParticle", NodeParticleBlockConnectionPointTypes.SolidParticle);
}

public override getClassName() {
return "SPSCreateBlock";
}

public get mesh(): NodeParticleConnectionPoint {
return this._inputs[0];
}

public get count(): NodeParticleConnectionPoint {
return this._inputs[1];
}

public get material(): NodeParticleConnectionPoint {
return this._inputs[2];
}

public get initBlock(): NodeParticleConnectionPoint {
return this._inputs[3];
}

public get updateBlock(): NodeParticleConnectionPoint {
return this._inputs[4];
}

public get solidParticle(): NodeParticleConnectionPoint {
return this._outputs[0];
}

public override _build(state: NodeParticleBuildState) {
const mesh = this.mesh.getConnectedValue(state);
const count = (this.count.getConnectedValue(state) as number) || 1;
const material = this.material.getConnectedValue(state);

const initBlock = this.initBlock.isConnected ? this.initBlock.getConnectedValue(state) : null;
const updateBlock = this.updateBlock.isConnected ? this.updateBlock.getConnectedValue(state) : null;

const solidParticle: ISPSCreateData = {
mesh,
count,
material,
initBlock,
updateBlock,
};

this.solidParticle._storedValue = solidParticle;
}
}

RegisterClass("BABYLON.SPSCreateBlock", SPSCreateBlock);
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { RegisterClass } from "../../../../Misc/typeStore";
import { NodeParticleBlockConnectionPointTypes } from "../../Enums/nodeParticleBlockConnectionPointTypes";
import { NodeParticleBlock } from "../../nodeParticleBlock";
import type { NodeParticleConnectionPoint } from "../../nodeParticleBlockConnectionPoint";
import type { NodeParticleBuildState } from "../../nodeParticleBuildState";
import { Vector3 } from "core/Maths/math.vector";
import { Color4 } from "core/Maths/math.color";
import type { ISPSUpdateData } from "./ISPSData";

/**
* Block used to generate initialization function for SPS particles
*/
export class SPSInitBlock extends NodeParticleBlock {
public constructor(name: string) {
super(name);

this.registerInput("position", NodeParticleBlockConnectionPointTypes.Vector3, true);
this.registerInput("velocity", NodeParticleBlockConnectionPointTypes.Vector3, true);
this.registerInput("color", NodeParticleBlockConnectionPointTypes.Color4, true);
this.registerInput("scaling", NodeParticleBlockConnectionPointTypes.Vector3, true);
this.registerInput("rotation", NodeParticleBlockConnectionPointTypes.Vector3, true);

this.registerOutput("initData", NodeParticleBlockConnectionPointTypes.System);
}

public override getClassName() {
return "SPSInitBlock";
}

public get initData(): NodeParticleConnectionPoint {
return this._outputs[0];
}

public get position(): NodeParticleConnectionPoint {
return this._inputs[0];
}

public get velocity(): NodeParticleConnectionPoint {
return this._inputs[1];
}

public get color(): NodeParticleConnectionPoint {
return this._inputs[2];
}

public get scaling(): NodeParticleConnectionPoint {
return this._inputs[3];
}

public get rotation(): NodeParticleConnectionPoint {
return this._inputs[4];
}

public override _build(state: NodeParticleBuildState) {
const initData = {} as ISPSUpdateData;
initData.position = () => {
return this.getPosition(state);
};
initData.velocity = () => {
return this.getVelocity(state);
};
initData.color = () => {
return this.getColor(state);
};
initData.scaling = () => {
return this.getScaling(state);
};
initData.rotation = () => {
return this.getRotation(state);
};

this.initData._storedValue = initData;
}

private getPosition(state: NodeParticleBuildState) {
if (this.position.isConnected) {
if (this.position._storedFunction) {
return this.position._storedFunction!(state);
}
return this.position.getConnectedValue(state);
}
return new Vector3(0, 0, 0);
}
private getVelocity(state: NodeParticleBuildState) {
if (this.velocity.isConnected) {
if (this.velocity._storedFunction) {
return this.velocity._storedFunction!(state);
}
return this.velocity.getConnectedValue(state);
}
return new Vector3(0, 0, 0);
}
private getColor(state: NodeParticleBuildState) {
if (this.color.isConnected) {
if (this.color._storedFunction) {
return this.color._storedFunction!(state);
}
return this.color.getConnectedValue(state);
}
return new Color4(1, 1, 1, 1);
}
private getScaling(state: NodeParticleBuildState) {
if (this.scaling.isConnected) {
if (this.scaling._storedFunction) {
return this.scaling._storedFunction!(state);
}
return this.scaling.getConnectedValue(state);
}
return new Vector3(1, 1, 1);
}
private getRotation(state: NodeParticleBuildState) {
if (this.rotation.isConnected) {
if (this.rotation._storedFunction) {
return this.rotation._storedFunction!(state);
}
return this.rotation.getConnectedValue(state);
}
return new Vector3(0, 0, 0);
}
public override serialize(): any {
const serializationObject = super.serialize();
return serializationObject;
}

public override _deserialize(serializationObject: any) {
super._deserialize(serializationObject);
}
}

RegisterClass("BABYLON.SPSInitBlock", SPSInitBlock);
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Mesh shape types for SPS
*/
export enum SPSMeshShapeType {
Box = 0,
Sphere = 1,
Cylinder = 2,
Plane = 3,
Custom = 4,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { RegisterClass } from "../../../../Misc/typeStore";
import { NodeParticleBlockConnectionPointTypes } from "../../Enums/nodeParticleBlockConnectionPointTypes";
import { NodeParticleBlock } from "../../nodeParticleBlock";
import type { NodeParticleConnectionPoint } from "../../nodeParticleBlockConnectionPoint";
import type { NodeParticleBuildState } from "../../nodeParticleBuildState";
import { editableInPropertyPage, PropertyTypeForEdition } from "core/Decorators/nodeDecorator";
import { CreateBox } from "core/Meshes/Builders/boxBuilder";
import { CreateSphere } from "core/Meshes/Builders/sphereBuilder";
import { CreateCylinder } from "core/Meshes/Builders/cylinderBuilder";
import { CreatePlane } from "core/Meshes/Builders/planeBuilder";
import { SPSMeshShapeType } from "./SPSMeshShapeType";

/**
* Block used to provide mesh source for SPS
*/
export class SPSMeshSourceBlock extends NodeParticleBlock {
@editableInPropertyPage("Shape Type", PropertyTypeForEdition.List, "ADVANCED", {
notifiers: { rebuild: true },
embedded: true,
options: [
{ label: "Box", value: SPSMeshShapeType.Box },
{ label: "Sphere", value: SPSMeshShapeType.Sphere },
{ label: "Cylinder", value: SPSMeshShapeType.Cylinder },
{ label: "Plane", value: SPSMeshShapeType.Plane },
{ label: "Custom", value: SPSMeshShapeType.Custom },
],
})
public shapeType = SPSMeshShapeType.Box;

@editableInPropertyPage("Size", PropertyTypeForEdition.Float, "ADVANCED", {
embedded: true,
min: 0.01,
})
public size = 1;

@editableInPropertyPage("Segments", PropertyTypeForEdition.Int, "ADVANCED", {
embedded: true,
min: 1,
})
public segments = 16;

public constructor(name: string) {
super(name);

this.registerInput("customMesh", NodeParticleBlockConnectionPointTypes.Mesh, true);
this.registerOutput("mesh", NodeParticleBlockConnectionPointTypes.Mesh);
}

public override getClassName() {
return "SPSMeshSourceBlock";
}

public get customMesh(): NodeParticleConnectionPoint {
return this._inputs[0];
}

public get mesh(): NodeParticleConnectionPoint {
return this._outputs[0];
}

public override _build(state: NodeParticleBuildState) {
let mesh;

if (this.shapeType === SPSMeshShapeType.Custom) {
if (this.customMesh.isConnected) {
const customMesh = this.customMesh.getConnectedValue(state);
if (customMesh) {
mesh = customMesh;
} else {
mesh = CreateBox("sps_mesh_source", { size: this.size }, state.scene);
}
} else {
mesh = CreateBox("sps_mesh_source", { size: this.size }, state.scene);
}
} else {
switch (this.shapeType) {
case SPSMeshShapeType.Box:
mesh = CreateBox("sps_mesh_source", { size: this.size }, state.scene);
break;
case SPSMeshShapeType.Sphere:
mesh = CreateSphere("sps_mesh_source", { diameter: this.size, segments: this.segments }, state.scene);
break;
case SPSMeshShapeType.Cylinder:
mesh = CreateCylinder("sps_mesh_source", { height: this.size, diameter: this.size, tessellation: this.segments }, state.scene);
break;
case SPSMeshShapeType.Plane:
mesh = CreatePlane("sps_mesh_source", { size: this.size }, state.scene);
break;
default:
mesh = CreateBox("sps_mesh_source", { size: this.size }, state.scene);
break;
}
}

this.mesh._storedValue = mesh;
}

public override serialize(): any {
const serializationObject = super.serialize();
serializationObject.shapeType = this.shapeType;
serializationObject.size = this.size;
serializationObject.segments = this.segments;
return serializationObject;
}

public override _deserialize(serializationObject: any) {
super._deserialize(serializationObject);
this.shapeType = serializationObject.shapeType || SPSMeshShapeType.Box;
this.size = serializationObject.size || 1;
this.segments = serializationObject.segments || 16;
}
}

RegisterClass("BABYLON.SPSMeshSourceBlock", SPSMeshSourceBlock);
Loading
Loading