Skip to content

Commit ad62b61

Browse files
deltakoshDavid Catuhe
andauthored
Fix #16989 (#17013)
Co-authored-by: David Catuhe <[email protected]>
1 parent 040ac66 commit ad62b61

File tree

7 files changed

+109
-1
lines changed

7 files changed

+109
-1
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { RegisterClass } from "../../../../Misc/typeStore";
2+
import { NodeParticleBlockConnectionPointTypes } from "../../Enums/nodeParticleBlockConnectionPointTypes";
3+
import { NodeParticleBlock } from "../../nodeParticleBlock";
4+
import type { NodeParticleConnectionPoint } from "../../nodeParticleBlockConnectionPoint";
5+
import type { NodeParticleBuildState } from "../../nodeParticleBuildState";
6+
import type { ThinParticleSystem } from "core/Particles/thinParticleSystem";
7+
import type { Particle } from "core/Particles/particle";
8+
import { _ConnectAtTheEnd } from "core/Particles/Queue/executionQueue";
9+
import { Vector3 } from "../../../../Maths/math.vector";
10+
import { editableInPropertyPage, PropertyTypeForEdition } from "../../../../Decorators/nodeDecorator";
11+
12+
/**
13+
* Block used to align the angle of a particle to its direction
14+
* We assume the sprite is facing +Y
15+
* NPE: #W5054F
16+
* PG: #H5RP91
17+
*/
18+
export class AlignAngleBlock extends NodeParticleBlock {
19+
/**
20+
* Gets or sets the strenght of the flow map effect
21+
*/
22+
@editableInPropertyPage("alignment", PropertyTypeForEdition.Float, "ADVANCED", { embedded: true, notifiers: { rebuild: true }, min: -0, max: 2 * Math.PI })
23+
public alignment = Math.PI / 2; // Default to 90 degrees, aligning +Y with direction
24+
25+
/**
26+
* Create a new AlignAngleBlock
27+
* @param name defines the block name
28+
*/
29+
public constructor(name: string) {
30+
super(name);
31+
32+
this.registerInput("particle", NodeParticleBlockConnectionPointTypes.Particle);
33+
this.registerOutput("output", NodeParticleBlockConnectionPointTypes.Particle);
34+
}
35+
36+
/**
37+
* Gets the particle component
38+
*/
39+
public get particle(): NodeParticleConnectionPoint {
40+
return this._inputs[0];
41+
}
42+
43+
/**
44+
* Gets the output component
45+
*/
46+
public get output(): NodeParticleConnectionPoint {
47+
return this._outputs[0];
48+
}
49+
50+
/**
51+
* Gets the current class name
52+
* @returns the class name
53+
*/
54+
public override getClassName() {
55+
return "AlignAngleBlock";
56+
}
57+
58+
/**
59+
* Builds the block
60+
* @param state defines the current build state
61+
*/
62+
public override _build(state: NodeParticleBuildState) {
63+
const system = this.particle.getConnectedValue(state) as ThinParticleSystem;
64+
65+
this.output._storedValue = system;
66+
67+
const tempVector3 = new Vector3();
68+
69+
const processAngle = (particle: Particle) => {
70+
const cam = state.scene.activeCamera;
71+
if (!cam) {
72+
return;
73+
}
74+
const dir = particle.direction;
75+
const view = cam.getViewMatrix();
76+
77+
const dirInView = Vector3.TransformNormalToRef(dir, view, tempVector3);
78+
79+
// Angle so sprite’s +Y aligns with projected direction
80+
const angle = Math.atan2(dirInView.y, dirInView.x) + this.alignment;
81+
particle.angle = angle; // radians
82+
};
83+
84+
const angleProcessing = {
85+
process: processAngle,
86+
previousItem: null,
87+
nextItem: null,
88+
};
89+
90+
if (system._updateQueueStart) {
91+
_ConnectAtTheEnd(angleProcessing, system._updateQueueStart);
92+
} else {
93+
system._updateQueueStart = angleProcessing;
94+
}
95+
}
96+
}
97+
98+
RegisterClass("BABYLON.AlignAngleBlock", AlignAngleBlock);

packages/dev/core/src/Particles/Node/Blocks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export * from "./Update/basicSpriteUpdateBlock";
1515
export * from "./Update/updateSpriteCellIndexBlock";
1616
export * from "./Update/updateFlowMapBlock";
1717
export * from "./Update/updateAttractorBlock";
18+
export * from "./Update/alignAngleBlock";
1819
export * from "./Emitters/index";
1920
export * from "./particleGradientValueBlock";
2021
export * from "./particleGradientBlock";

packages/dev/core/src/Particles/Node/nodeParticleSystemSet.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ export interface INodeParticleEditorOptions {
4040

4141
/**
4242
* Defines a set of particle systems defined as a node graph.
43-
* @experimental This API is experimental and may change in future releases.
4443
* NPE: #K6F1ZB#1
4544
* PG: #ZT509U#1
4645
*/

packages/tools/nodeParticleEditor/src/blockTools.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,16 @@ import { CustomShapeBlock } from "core/Particles/Node/Blocks/Emitters/customShap
3636
import { CylinderShapeBlock } from "core/Particles/Node/Blocks/Emitters/cylinderShapeBlock";
3737
import { MeshShapeBlock } from "core/Particles/Node/Blocks/Emitters/meshShapeBlock";
3838
import { UpdateAttractorBlock } from "core/Particles/Node/Blocks/Update/updateAttractorBlock";
39+
import { AlignAngleBlock } from "core/Particles/Node/Blocks/Update/alignAngleBlock";
3940

4041
/**
4142
* Static class for BlockTools
4243
*/
4344
export class BlockTools {
4445
public static GetBlockFromString(data: string) {
4546
switch (data) {
47+
case "AlignAngleBlock":
48+
return new AlignAngleBlock("Align angle");
4649
case "CreateParticleBlock":
4750
return new CreateParticleBlock("Create particle");
4851
case "EqualBlock": {

packages/tools/nodeParticleEditor/src/components/nodeList/nodeListComponent.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
111111
OrBlock: "Conditional block set to Or",
112112
AndBlock: "Conditional block set to And",
113113
CreateParticleBlock: "Block used to create a particle with properties such as emit power, lifetime, color, scale, and angle",
114+
AlignAngleBlock: "Block used to align the angle of a particle to its direction",
114115
};
115116

116117
private _customFrameList: { [key: string]: string };
@@ -209,6 +210,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
209210
"UpdateSpriteCellIndexBlock",
210211
"UpdateFlowMapBlock",
211212
"UpdateAttractorBlock",
213+
"AlignAngleBlock",
212214
],
213215
Triggers: ["TriggerBlock"],
214216
Setup: ["CreateParticleBlock", "SetupSpriteSheetBlock"],
5.31 KB
Loading

packages/tools/tests/test/visualization/config.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
{
22
"root": "https://cdn.babylonjs.com",
33
"tests": [
4+
{
5+
"title": "NPE - Angle align",
6+
"playgroundId": "#H5RP91",
7+
"referenceImage": "npe-angle-align.png"
8+
},
49
{
510
"title": "SPZ v3 - Splat",
611
"playgroundId": "#V7CV8W#3",

0 commit comments

Comments
 (0)