Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 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
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
4 changes: 2 additions & 2 deletions packages/dev/core/src/Decorators/nodeDecorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ export const enum PropertyTypeForEdition {
Color3,
/** property is a Color4 */
Color4,
/** property is a string */
String,
/** property (int) should be edited as a combo box with a list of sampling modes */
SamplingMode,
/** property (int) should be edited as a combo box with a list of texture formats */
TextureFormat,
/** property (int) should be edited as a combo box with a list of texture types */
TextureType,
/** property is a string */
String,
/** property is a matrix */
Matrix,
/** property is a viewport */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { Vector3 } from "core/Maths/math.vector";
import type { Color4 } from "core/Maths/math.color";
import type { Mesh } from "core/Meshes/mesh";
import type { Material } from "core/Materials/material";

/**
* Interface for SPS update block data
*/
export interface ISpsUpdateData {
position?: () => Vector3;
velocity?: () => Vector3;
color?: () => Color4;
scaling?: () => Vector3;
rotation?: () => Vector3;
}

/**
* Interface for SPS create block data
*/
export interface ISpsParticleConfigData {
mesh: Mesh;
count: number;
material?: Material;
initBlock?: ISpsUpdateData;
updateBlock?: ISpsUpdateData;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
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 { SolidParticle } from "../../../solidParticle";
import { editableInPropertyPage, PropertyTypeForEdition } from "../../../../Decorators/nodeDecorator";
import { serialize } from "../../../../Misc/decorators";

/**
* Block used to get custom properties from particle.props
* Works similar to contextual blocks but for dynamic property names
*/
export class SpsParticlePropsGetBlock extends NodeParticleBlock {
/**
* Gets or sets the property name to read from particle.props
*/
@serialize("propertyName")
@editableInPropertyPage("Property Name", PropertyTypeForEdition.String, "PROPERTIES", {
embedded: false,
notifiers: { rebuild: true },
})
public propertyName: string = "value";

/**
* Gets or sets the connection point type (default float)
*/
private _type: NodeParticleBlockConnectionPointTypes = NodeParticleBlockConnectionPointTypes.Float;

/**
* Gets the value to display (returns propertyName as string)
*/
public get displayValue(): string {
return this.propertyName || "value";
}

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

this.registerOutput("output", NodeParticleBlockConnectionPointTypes.AutoDetect);
// Set default type
(this._outputs[0] as any)._defaultConnectionPointType = this._type;
}

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

/**
* Gets or sets the connection point type
*/
public get type(): NodeParticleBlockConnectionPointTypes {
return this._type;
}

public set type(value: NodeParticleBlockConnectionPointTypes) {
if (this._type !== value) {
this._type = value;
// Update output type
(this._outputs[0] as any)._type = value;
(this._outputs[0] as any)._defaultConnectionPointType = value;
}
}

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

public override _build(state: NodeParticleBuildState) {
// Validate property name
if (!this.propertyName || this.propertyName.trim() === "") {
this.output._storedFunction = null;
this.output._storedValue = null;
return;
}

// Validate type
if (this._type === NodeParticleBlockConnectionPointTypes.Undefined || this._type === NodeParticleBlockConnectionPointTypes.AutoDetect) {
this._type = NodeParticleBlockConnectionPointTypes.Float;
(this._outputs[0] as any)._type = this._type;
(this._outputs[0] as any)._defaultConnectionPointType = this._type;
}

const propertyName = this.propertyName;

const func = (state: NodeParticleBuildState) => {
if (!state.particleContext) {
return null;
}

const particle = state.particleContext as SolidParticle;

if (!particle.props) {
return null;
}

const value = particle.props[propertyName];

if (value === undefined) {
return null;
}

return value;
};

if (this.output.isConnected) {
this.output._storedFunction = func;
} else {
this.output._storedValue = func(state);
}
}

public override serialize(): any {
const serializationObject = super.serialize();
serializationObject.propertyName = this.propertyName;
serializationObject.type = this._type;
return serializationObject;
}

public override _deserialize(serializationObject: any) {
super._deserialize(serializationObject);
this.propertyName = serializationObject.propertyName || "value";
this._type = serializationObject.type || NodeParticleBlockConnectionPointTypes.Float;
(this._outputs[0] as any)._type = this._type;
(this._outputs[0] as any)._defaultConnectionPointType = this._type;
}
}

RegisterClass("BABYLON.SpsParticlePropsGetBlock", SpsParticlePropsGetBlock);
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
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 { SolidParticle } from "../../../solidParticle";
import { editableInPropertyPage, PropertyTypeForEdition } from "../../../../Decorators/nodeDecorator";
import { serialize } from "../../../../Misc/decorators";

/**
* Block used to set custom properties in particle.props
* Works as a side-effect block that stores values and passes them through
*/
export class SpsParticlePropsSetBlock extends NodeParticleBlock {
/**
* Gets or sets the property name to store in particle.props
*/
@serialize("propertyName")
@editableInPropertyPage("Property Name", PropertyTypeForEdition.String, "PROPERTIES", {
embedded: false,
notifiers: { rebuild: true },
})
public propertyName: string = "value";

/**
* Gets or sets the connection point type (default float)
*/
private _type: NodeParticleBlockConnectionPointTypes = NodeParticleBlockConnectionPointTypes.Float;

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

this.registerInput("value", NodeParticleBlockConnectionPointTypes.AutoDetect, true);
this.registerOutput("output", NodeParticleBlockConnectionPointTypes.BasedOnInput);

// Link output type to input type
this._outputs[0]._typeConnectionSource = this._inputs[0];
// Set default type for when input is not connected
(this._outputs[0] as any)._defaultConnectionPointType = this._type;
}

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

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

/**
* Gets the value to display (returns propertyName as string)
* This shadows the connection point name for display purposes
*/
public get displayValue(): string {
return this.propertyName || "value";
}

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

/**
* Gets or sets the connection point type
*/
public get type(): NodeParticleBlockConnectionPointTypes {
return this._type;
}

public set type(value: NodeParticleBlockConnectionPointTypes) {
if (this._type !== value) {
this._type = value;
// Update default type (used when input is not connected)
(this._outputs[0] as any)._defaultConnectionPointType = value;
}
}

public override _build(state: NodeParticleBuildState) {
// Validate property name
if (!this.propertyName || this.propertyName.trim() === "") {
this.output._storedFunction = null;
this.output._storedValue = null;
return;
}

if (!this.value.isConnected) {
this.output._storedFunction = null;
this.output._storedValue = null;
return;
}

const propertyName = this.propertyName;

const func = (state: NodeParticleBuildState) => {
if (!state.particleContext) {
return null;
}

const particle = state.particleContext as SolidParticle;

const value = this.value.getConnectedValue(state);

if (!particle.props) {
particle.props = {};
}

particle.props[propertyName] = value;

return value;
};

if (this.output.isConnected) {
this.output._storedFunction = func;
} else {
this.output._storedValue = func(state);
}
}

public override serialize(): any {
const serializationObject = super.serialize();
serializationObject.propertyName = this.propertyName;
serializationObject.type = this._type;
return serializationObject;
}

public override _deserialize(serializationObject: any) {
super._deserialize(serializationObject);
this.propertyName = serializationObject.propertyName || "value";
this._type = serializationObject.type || NodeParticleBlockConnectionPointTypes.Float;
(this._outputs[0] as any)._defaultConnectionPointType = this._type;
}
}

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