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.

356 lines 12.1 kB
import { __decorate } from "../../tslib.es6.js"; import { serialize } from "../../Misc/decorators.js"; import { UniqueIdGenerator } from "../../Misc/uniqueIdGenerator.js"; import { NodeParticleConnectionPoint } from "./nodeParticleBlockConnectionPoint.js"; import { Logger } from "../../Misc/logger.js"; import { Observable } from "../../Misc/observable.js"; import { GetClass } from "../../Misc/typeStore.js"; /** * Defines a block that can be used inside a node based particle system */ export class NodeParticleBlock { /** * Gets a boolean indicating if this block is a teleport out */ get isTeleportOut() { return this._isTeleportOut; } /** * Gets a boolean indicating if this block is a teleport in */ get isTeleportIn() { return this._isTeleportIn; } /** * Gets a boolean indicating that this block is a system block */ get isSystem() { return this._isSystem; } /** * Gets a boolean indicating that this block is an input block */ get isInput() { return this._isInput; } /** * Gets a boolean indicating if this block is a debug block */ get isDebug() { return this._isDebug; } /** * Gets or set the name of the block */ get name() { return this._name; } set name(value) { this._name = value; } /** * Gets the current class name e.g. "NodeParticleBlock" * @returns the class name */ getClassName() { return "NodeParticleBlock"; } /** * Gets the list of input points */ get inputs() { return this._inputs; } /** Gets the list of output points */ get outputs() { return this._outputs; } /** * Creates a new NodeParticleBlock * @param name defines the block name */ constructor(name) { this._name = ""; this._isInput = false; this._isSystem = false; this._isDebug = false; this._isTeleportOut = false; this._isTeleportIn = false; /** @internal */ this._inputs = new Array(); /** @internal */ this._outputs = new Array(); /** * Gets an observable raised when the block is built */ this.onBuildObservable = new Observable(); /** * Gets an observable raised when the block is disposed */ this.onDisposeObservable = new Observable(); /** * Gets an observable raised when the inputs of the block change */ this.onInputChangedObservable = new Observable(); /** Gets or sets a boolean indicating that this input can be edited from a collapsed frame */ this.visibleOnFrame = false; this._name = name; this.uniqueId = UniqueIdGenerator.UniqueId; } _inputRename(name) { return name; } _outputRename(name) { return name; } /** * Checks if the current block is an ancestor of a given block * @param block defines the potential descendant block to check * @returns true if block is a descendant */ isAnAncestorOf(block) { for (const output of this._outputs) { if (!output.hasEndpoints) { continue; } for (const endpoint of output.endpoints) { if (endpoint.ownerBlock === block) { return true; } if (endpoint.ownerBlock.isAnAncestorOf(block)) { return true; } } } return false; } /** * Checks if the current block is an ancestor of a given type * @param type defines the potential type to check * @returns true if block is a descendant */ isAnAncestorOfType(type) { if (this.getClassName() === type) { return true; } for (const output of this._outputs) { if (!output.hasEndpoints) { continue; } for (const endpoint of output.endpoints) { if (endpoint.ownerBlock.isAnAncestorOfType(type)) { return true; } } } return false; } /** * Find an input by its name * @param name defines the name of the input to look for * @returns the input or null if not found */ getInputByName(name) { const filter = this._inputs.filter((e) => e.name === name); if (filter.length) { return filter[0]; } return null; } _linkConnectionTypes(inputIndex0, inputIndex1, looseCoupling = false) { if (looseCoupling) { this._inputs[inputIndex1]._acceptedConnectionPointType = this._inputs[inputIndex0]; } else { this._inputs[inputIndex0]._linkedConnectionSource = this._inputs[inputIndex1]; this._inputs[inputIndex0]._isMainLinkSource = true; } this._inputs[inputIndex1]._linkedConnectionSource = this._inputs[inputIndex0]; } /** * Register a new input. Must be called inside a block constructor * @param name defines the connection point name * @param type defines the connection point type * @param isOptional defines a boolean indicating that this input can be omitted * @param value value to return if there is no connection * @param valueMin min value accepted for value * @param valueMax max value accepted for value * @returns the current block */ registerInput(name, type, isOptional = false, value, valueMin, valueMax) { const point = new NodeParticleConnectionPoint(name, this, 0 /* NodeParticleConnectionPointDirection.Input */); point.type = type; point.isOptional = isOptional; point.defaultValue = value; point.value = value; point.valueMin = valueMin; point.valueMax = valueMax; this._inputs.push(point); this.onInputChangedObservable.notifyObservers(point); return this; } /** * Register a new output. Must be called inside a block constructor * @param name defines the connection point name * @param type defines the connection point type * @param point an already created connection point. If not provided, create a new one * @returns the current block */ registerOutput(name, type, point) { point = point ?? new NodeParticleConnectionPoint(name, this, 1 /* NodeParticleConnectionPointDirection.Output */); point.type = type; this._outputs.push(point); return this; } /** * Builds the block. Must be implemented by derived classes. * @param _state defines the current build state */ _build(_state) { } _customBuildStep(_state) { // Must be implemented by children } /** * Builds the block * @param state defines the current build state * @returns the built block */ build(state) { if (this._buildId === state.buildId) { return true; } if (this._outputs.length > 0) { if (!this._outputs.some((o) => o.hasEndpoints) && !this.isDebug && !this.isSystem) { return false; } } this._buildId = state.buildId; // Check if "parent" blocks are compiled for (const input of this._inputs) { if (!input.connectedPoint) { if (!input.isOptional) { // Emit a warning state.notConnectedNonOptionalInputs.push(input); } continue; } const block = input.connectedPoint.ownerBlock; if (block && block !== this && !block.isSystem) { block.build(state); } } this._customBuildStep(state); // Logs if (state.verbose) { Logger.Log(`Building ${this.name} [${this.getClassName()}]`); } this._build(state); this.onBuildObservable.notifyObservers(this); return false; } /** * Serializes this block in a JSON representation * @returns the serialized block object */ serialize() { const serializationObject = {}; serializationObject.customType = "BABYLON." + this.getClassName(); serializationObject.id = this.uniqueId; serializationObject.name = this.name; serializationObject.visibleOnFrame = this.visibleOnFrame; serializationObject.comments = this.comments; serializationObject.inputs = []; serializationObject.outputs = []; for (const input of this.inputs) { serializationObject.inputs.push(input.serialize()); } for (const output of this.outputs) { serializationObject.outputs.push(output.serialize(false)); } return serializationObject; } /** * @internal */ _deserialize(serializationObject) { this._name = serializationObject.name; this.comments = serializationObject.comments; this.visibleOnFrame = !!serializationObject.visibleOnFrame; this._deserializePortDisplayNamesAndExposedOnFrame(serializationObject); } _deserializePortDisplayNamesAndExposedOnFrame(serializationObject) { const serializedInputs = serializationObject.inputs; const serializedOutputs = serializationObject.outputs; if (serializedInputs) { for (const port of serializedInputs) { const input = this.inputs.find((i) => i.name === port.name); if (!input) { return; } if (port.displayName) { input.displayName = port.displayName; } if (port.isExposedOnFrame) { input.isExposedOnFrame = port.isExposedOnFrame; input.exposedPortPosition = port.exposedPortPosition; } if (port.value !== undefined && port.value !== null) { if (port.valueType === "number") { input.value = port.value; } else { const valueType = GetClass(port.valueType); if (valueType) { input.value = valueType.FromArray(port.value); } } } } } if (serializedOutputs) { for (let i = 0; i < serializedOutputs.length; i++) { const port = serializedOutputs[i]; if (port.displayName) { this.outputs[i].displayName = port.displayName; } if (port.isExposedOnFrame) { this.outputs[i].isExposedOnFrame = port.isExposedOnFrame; this.outputs[i].exposedPortPosition = port.exposedPortPosition; } } } } /** * Clone the current block to a new identical block * @returns a copy of the current block */ clone() { const serializationObject = this.serialize(); const blockType = GetClass(serializationObject.customType); if (blockType) { const block = new blockType(); block._deserialize(serializationObject); return block; } return null; } /** * Release resources */ dispose() { this.onDisposeObservable.notifyObservers(this); this.onDisposeObservable.clear(); for (const input of this.inputs) { input.dispose(); } for (const output of this.outputs) { output.dispose(); } this.onBuildObservable.clear(); this.onInputChangedObservable.clear(); } } __decorate([ serialize("comment") ], NodeParticleBlock.prototype, "comments", void 0); //# sourceMappingURL=nodeParticleBlock.js.map