UNPKG

@babylonjs/core

Version:

Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.

349 lines (348 loc) 15.5 kB
import { __decorate } from "../../../tslib.es6.js"; import { editableInPropertyPage } from "../../../Decorators/nodeDecorator.js"; import { RegisterClass } from "../../../Misc/typeStore.js"; import { Vector2, Vector3 } from "../../../Maths/math.vector.js"; import { Color4 } from "../../../Maths/math.color.js"; import { BaseParticleSystem } from "../../baseParticleSystem.js"; import { NodeParticleBlock } from "../nodeParticleBlock.js"; import { _TriggerSubEmitter } from "./Triggers/triggerTools.js"; import { NodeParticleBlockConnectionPointTypes } from "../Enums/nodeParticleBlockConnectionPointTypes.js"; /** * Block used to get a system of particles */ export class SystemBlock extends NodeParticleBlock { /** * Create a new SystemBlock * @param name defines the block name */ constructor(name) { super(name); /** * Gets or sets the blend mode for the particle system */ this.blendMode = BaseParticleSystem.BLENDMODE_ONEONE; /** * Gets or sets the epsilon value used for comparison */ this.capacity = 1000; /** * Gets or sets the manual emit count */ this.manualEmitCount = -1; /** * Gets or sets the target stop duration for the particle system */ this.startDelay = 0; /** * Gets or sets the target stop duration for the particle system */ this.updateSpeed = 0.0167; /** * Gets or sets the number of pre-warm cycles before rendering the particle system */ this.preWarmCycles = 0; /** * Gets or sets the time step multiplier used for pre-warm */ this.preWarmStepOffset = 0; /** * Gets or sets a boolean indicating if the system is billboard based */ this.isBillboardBased = true; /** * Gets or sets the billboard mode for the particle system */ this.billBoardMode = 7; /** * Gets or sets a boolean indicating if the system coordinate space is local or global */ this.isLocal = false; /** * Gets or sets a boolean indicating if the system should be disposed when stopped */ this.disposeOnStop = false; /** * Gets or sets a boolean indicating if the system should not start automatically */ this.doNoStart = false; /** * Gets or sets the rendering group id for the particle system (0 by default) */ this.renderingGroupId = 0; /** @internal */ this._internalId = SystemBlock._IdCounter++; /** * Gets or sets the custom shader configuration used to render the particles. * This can be used to set your own shader to render the particle system. */ this.customShader = null; /** * Gets or sets the emitter for the particle system. */ this.emitter = Vector3.Zero(); this._isSystem = true; this.registerInput("particle", NodeParticleBlockConnectionPointTypes.Particle); this.registerInput("emitRate", NodeParticleBlockConnectionPointTypes.Int, true, 10, 0); this.registerInput("texture", NodeParticleBlockConnectionPointTypes.Texture); this.registerInput("translationPivot", NodeParticleBlockConnectionPointTypes.Vector2, true); this.registerInput("textureMask", NodeParticleBlockConnectionPointTypes.Color4, true); this.registerInput("targetStopDuration", NodeParticleBlockConnectionPointTypes.Float, true, 0, 0); this.registerInput("onStart", NodeParticleBlockConnectionPointTypes.System, true); this.registerInput("onEnd", NodeParticleBlockConnectionPointTypes.System, true); this.registerOutput("system", NodeParticleBlockConnectionPointTypes.System); } /** * Gets the current class name * @returns the class name */ getClassName() { return "SystemBlock"; } /** * Gets the particle input component */ get particle() { return this._inputs[0]; } /** * Gets the emitRate input component */ get emitRate() { return this._inputs[1]; } /** * Gets the texture input component */ get texture() { return this._inputs[2]; } /** * Gets the translationPivot input component */ get translationPivot() { return this._inputs[3]; } /** * Gets the textureMask input component */ get textureMask() { return this._inputs[4]; } /** * Gets the targetStopDuration input component */ get targetStopDuration() { return this._inputs[5]; } /** * Gets the onStart input component */ get onStart() { return this._inputs[6]; } /** * Gets the onEnd input component */ get onEnd() { return this._inputs[7]; } /** * Gets the system output component */ get system() { return this._outputs[0]; } /** * Builds the block and return a functional particle system * @param state defines the building state * @returns the built particle system */ createSystem(state) { state.capacity = this.capacity; state.buildId = this._buildId++; this.build(state); const particleSystem = this.particle.getConnectedValue(state); particleSystem.particleTexture = this.texture.getConnectedValue(state); particleSystem.emitRate = this.emitRate.getConnectedValue(state); particleSystem.manualEmitCount = this.manualEmitCount; particleSystem.updateSpeed = this.updateSpeed; particleSystem.preWarmCycles = this.preWarmCycles; particleSystem.preWarmStepOffset = this.preWarmStepOffset; particleSystem.blendMode = this.blendMode; particleSystem.name = this.name; particleSystem._targetStopDuration = this.targetStopDuration.getConnectedValue(state) ?? 0; particleSystem.startDelay = this.startDelay; particleSystem.isBillboardBased = this.isBillboardBased; particleSystem.billboardMode = this.billBoardMode; particleSystem.translationPivot = this.translationPivot.getConnectedValue(state) || Vector2.Zero(); particleSystem.textureMask = this.textureMask.getConnectedValue(state) ?? new Color4(1, 1, 1, 1); particleSystem.isLocal = this.isLocal; particleSystem.disposeOnStop = this.disposeOnStop; particleSystem.renderingGroupId = this.renderingGroupId; if (this.emitter) { particleSystem.emitter = this.emitter; } // Apply custom shader if defined if (this.customShader) { const engine = particleSystem.getScene()?.getEngine(); if (engine?.createEffectForParticles) { const defines = this.customShader.shaderOptions.defines.length > 0 ? this.customShader.shaderOptions.defines.join("\n") : ""; const effect = engine.createEffectForParticles(this.customShader.shaderPath.fragmentElement, this.customShader.shaderOptions.uniforms, this.customShader.shaderOptions.samplers, defines); particleSystem.setCustomEffect(effect, 0); particleSystem.customShader = this.customShader; } } // The emit rate can vary if it is connected to another block like a gradient particleSystem._calculateEmitRate = () => { state.systemContext = particleSystem; return this.emitRate.getConnectedValue(state); }; this.system._storedValue = this; particleSystem.canStart = () => { return !this.doNoStart; }; particleSystem.onStartedObservable.add((system) => { // Triggers const onStartSystem = this.onStart.getConnectedValue(state); if (onStartSystem) { system.onStartedObservable.addOnce(() => { state.systemContext = particleSystem; const clone = _TriggerSubEmitter(onStartSystem, state.scene, state.emitterPosition); this.onDisposeObservable.addOnce(() => { // Clean up the cloned system when the original system is disposed clone.dispose(); }); }); } const onEndSystem = this.onEnd.getConnectedValue(state); if (onEndSystem) { system.onStoppedObservable.addOnce(() => { state.systemContext = particleSystem; const clone = _TriggerSubEmitter(onEndSystem, state.scene, state.emitterPosition); this.onDisposeObservable.addOnce(() => { // Clean up the cloned system when the original system is disposed clone.dispose(); }); }); } }); this.onDisposeObservable.addOnce(() => { particleSystem.dispose(); }); // Return return particleSystem; } /** * Serializes the system block * @returns The serialized object */ serialize() { const serializationObject = super.serialize(); serializationObject.capacity = this.capacity; serializationObject.manualEmitCount = this.manualEmitCount; serializationObject.blendMode = this.blendMode; serializationObject.updateSpeed = this.updateSpeed; serializationObject.preWarmCycles = this.preWarmCycles; serializationObject.preWarmStepOffset = this.preWarmStepOffset; serializationObject.isBillboardBased = this.isBillboardBased; serializationObject.billBoardMode = this.billBoardMode; serializationObject.isLocal = this.isLocal; serializationObject.disposeOnStop = this.disposeOnStop; serializationObject.doNoStart = this.doNoStart; serializationObject.renderingGroupId = this.renderingGroupId; serializationObject.startDelay = this.startDelay; serializationObject.customShader = this.customShader; return serializationObject; } /** * Deserializes the system block * @param serializationObject The serialized system */ _deserialize(serializationObject) { super._deserialize(serializationObject); this.capacity = serializationObject.capacity; this.manualEmitCount = serializationObject.manualEmitCount ?? -1; this.updateSpeed = serializationObject.updateSpeed ?? 0.0167; this.preWarmCycles = serializationObject.preWarmCycles ?? 0; this.preWarmStepOffset = serializationObject.preWarmStepOffset ?? 0; this.isBillboardBased = serializationObject.isBillboardBased ?? true; this.billBoardMode = serializationObject.billBoardMode ?? 7; this.isLocal = serializationObject.isLocal ?? false; this.disposeOnStop = serializationObject.disposeOnStop ?? false; this.doNoStart = !!serializationObject.doNoStart; this.renderingGroupId = serializationObject.renderingGroupId ?? 0; if (serializationObject.emitRate !== undefined) { this.emitRate.value = serializationObject.emitRate; } if (serializationObject.blendMode !== undefined) { this.blendMode = serializationObject.blendMode; } if (serializationObject.startDelay !== undefined) { this.startDelay = serializationObject.startDelay; } if (serializationObject.customShader !== undefined) { this.customShader = serializationObject.customShader; } } } SystemBlock._IdCounter = 0; __decorate([ editableInPropertyPage("Blend mode", 5 /* PropertyTypeForEdition.List */, "ADVANCED", { notifiers: { rebuild: true }, embedded: true, options: [ { label: "Blend Mode OneOne", value: BaseParticleSystem.BLENDMODE_ONEONE }, { label: "Blend Mode Standard", value: BaseParticleSystem.BLENDMODE_STANDARD }, { label: "Blend Mode Add", value: BaseParticleSystem.BLENDMODE_ADD }, { label: "Blend Mode Multiply", value: BaseParticleSystem.BLENDMODE_MULTIPLY }, { label: "Blend Mode MultiplyAdd", value: BaseParticleSystem.BLENDMODE_MULTIPLYADD }, ], }) ], SystemBlock.prototype, "blendMode", void 0); __decorate([ editableInPropertyPage("Capacity", 2 /* PropertyTypeForEdition.Int */, "ADVANCED", { embedded: true, notifiers: { rebuild: true }, min: 0, max: 10000 }) ], SystemBlock.prototype, "capacity", void 0); __decorate([ editableInPropertyPage("Manual emit count", 2 /* PropertyTypeForEdition.Int */, "ADVANCED", { embedded: true, notifiers: { rebuild: true }, min: -1 }) ], SystemBlock.prototype, "manualEmitCount", void 0); __decorate([ editableInPropertyPage("Delay start(ms)", 1 /* PropertyTypeForEdition.Float */, "ADVANCED", { embedded: true, notifiers: { rebuild: true }, min: 0 }) ], SystemBlock.prototype, "startDelay", void 0); __decorate([ editableInPropertyPage("updateSpeed", 1 /* PropertyTypeForEdition.Float */, "ADVANCED", { embedded: true, notifiers: { rebuild: true }, min: 0, max: 0.1 }) ], SystemBlock.prototype, "updateSpeed", void 0); __decorate([ editableInPropertyPage("Pre-warm cycles", 1 /* PropertyTypeForEdition.Float */, "ADVANCED", { embedded: true, notifiers: { rebuild: true }, min: 0 }) ], SystemBlock.prototype, "preWarmCycles", void 0); __decorate([ editableInPropertyPage("Pre-warm step multiplier", 1 /* PropertyTypeForEdition.Float */, "ADVANCED", { embedded: true, notifiers: { rebuild: true }, min: 0 }) ], SystemBlock.prototype, "preWarmStepOffset", void 0); __decorate([ editableInPropertyPage("Is billboard based", 0 /* PropertyTypeForEdition.Boolean */, "ADVANCED", { embedded: true, notifiers: { rebuild: true } }) ], SystemBlock.prototype, "isBillboardBased", void 0); __decorate([ editableInPropertyPage("Billboard mode", 5 /* PropertyTypeForEdition.List */, "ADVANCED", { notifiers: { rebuild: true }, embedded: true, options: [ { label: "Billboard Mode All", value: 7 }, { label: "Billboard Mode Y", value: 2 }, { label: "Billboard Mode Stretched", value: 8 }, { label: "Billboard Mode Stretched Local", value: 9 }, ], }) ], SystemBlock.prototype, "billBoardMode", void 0); __decorate([ editableInPropertyPage("Is local", 0 /* PropertyTypeForEdition.Boolean */, "ADVANCED", { embedded: true, notifiers: { rebuild: true } }) ], SystemBlock.prototype, "isLocal", void 0); __decorate([ editableInPropertyPage("Dispose on stop", 0 /* PropertyTypeForEdition.Boolean */, "ADVANCED", { embedded: true, notifiers: { rebuild: true } }) ], SystemBlock.prototype, "disposeOnStop", void 0); __decorate([ editableInPropertyPage("Do no start", 0 /* PropertyTypeForEdition.Boolean */, "ADVANCED", { embedded: true, notifiers: { rebuild: true } }) ], SystemBlock.prototype, "doNoStart", void 0); __decorate([ editableInPropertyPage("Rendering group id", 2 /* PropertyTypeForEdition.Int */, "ADVANCED", { embedded: true, notifiers: { rebuild: true }, min: 0 }) ], SystemBlock.prototype, "renderingGroupId", void 0); RegisterClass("BABYLON.SystemBlock", SystemBlock); //# sourceMappingURL=systemBlock.js.map