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.

440 lines 14.5 kB
import { __decorate } from "../tslib.es6.js"; import { serialize } from "../Misc/decorators.js"; import { RandomGUID } from "../Misc/guid.js"; import { defaultValueSerializationFunction } from "./serialization.js"; import { Observable } from "../Misc/observable.js"; import { GetFlowGraphAssetWithType } from "./flowGraphAssetsContext.js"; import { FlowGraphLogger } from "./flowGraphLogger.js"; /** * The context represents the current state and execution of the flow graph. * It contains both user-defined variables, which are derived from * a more general variable definition, and execution variables that * are set by the blocks. */ export class FlowGraphContext { /** * Enable logging on this context */ get enableLogging() { return this._enableLogging; } set enableLogging(value) { if (this._enableLogging === value) { return; } this._enableLogging = value; if (this._enableLogging) { this.logger = new FlowGraphLogger(); this.logger.logToConsole = true; } else { this.logger = null; } } constructor(params) { /** * A randomly generated GUID for each context. */ this.uniqueId = RandomGUID(); /** * These are the variables defined by a user. */ this._userVariables = {}; /** * These are the variables set by the blocks. */ this._executionVariables = {}; /** * A context-specific global variables, available to all blocks in the context. */ this._globalContextVariables = {}; /** * These are the values for the data connection points */ this._connectionValues = {}; /** * These are blocks that have currently pending tasks/listeners that need to be cleaned up. */ this._pendingBlocks = []; /** * A monotonically increasing ID for each execution. * Incremented for every block executed. */ this._executionId = 0; /** * Observable that is triggered when a node is executed. */ this.onNodeExecutedObservable = new Observable(); /** * Whether to treat data as right-handed. * This is used when serializing data from a right-handed system, while running the context in a left-handed system, for example in glTF parsing. * Default is false. */ this.treatDataAsRightHanded = false; this._enableLogging = false; this._configuration = params; this.assetsContext = params.assetsContext ?? params.scene; } /** * Check if a user-defined variable is defined. * @param name the name of the variable * @returns true if the variable is defined */ hasVariable(name) { return name in this._userVariables; } /** * Set a user-defined variable. * @param name the name of the variable * @param value the value of the variable */ setVariable(name, value) { this._userVariables[name] = value; this.logger?.addLogItem({ time: Date.now(), className: this.getClassName(), uniqueId: this.uniqueId, action: "ContextVariableSet" /* FlowGraphAction.ContextVariableSet */, payload: { name, value, }, }); } /** * Get an assets from the assets context based on its type and index in the array * @param type The type of the asset * @param index The index of the asset * @returns The asset or null if not found */ getAsset(type, index) { return GetFlowGraphAssetWithType(this.assetsContext, type, index); } /** * Get a user-defined variable. * @param name the name of the variable * @returns the value of the variable */ getVariable(name) { this.logger?.addLogItem({ time: Date.now(), className: this.getClassName(), uniqueId: this.uniqueId, action: "ContextVariableGet" /* FlowGraphAction.ContextVariableGet */, payload: { name, value: this._userVariables[name], }, }); return this._userVariables[name]; } /** * Gets all user variables map */ get userVariables() { return this._userVariables; } /** * Get the scene that the context belongs to. * @returns the scene */ getScene() { return this._configuration.scene; } _getUniqueIdPrefixedName(obj, name) { return `${obj.uniqueId}_${name}`; } /** * @internal * @param name name of the variable * @param defaultValue default value to return if the variable is not defined * @returns the variable value or the default value if the variable is not defined */ _getGlobalContextVariable(name, defaultValue) { this.logger?.addLogItem({ time: Date.now(), className: this.getClassName(), uniqueId: this.uniqueId, action: "GlobalVariableGet" /* FlowGraphAction.GlobalVariableGet */, payload: { name, defaultValue, possibleValue: this._globalContextVariables[name], }, }); if (this._hasGlobalContextVariable(name)) { return this._globalContextVariables[name]; } else { return defaultValue; } } /** * Set a global context variable * @internal * @param name the name of the variable * @param value the value of the variable */ _setGlobalContextVariable(name, value) { this.logger?.addLogItem({ time: Date.now(), className: this.getClassName(), uniqueId: this.uniqueId, action: "GlobalVariableSet" /* FlowGraphAction.GlobalVariableSet */, payload: { name, value }, }); this._globalContextVariables[name] = value; } /** * Delete a global context variable * @internal * @param name the name of the variable */ _deleteGlobalContextVariable(name) { this.logger?.addLogItem({ time: Date.now(), className: this.getClassName(), uniqueId: this.uniqueId, action: "GlobalVariableDelete" /* FlowGraphAction.GlobalVariableDelete */, payload: { name }, }); delete this._globalContextVariables[name]; } /** * Check if a global context variable is defined * @internal * @param name the name of the variable * @returns true if the variable is defined */ _hasGlobalContextVariable(name) { return name in this._globalContextVariables; } /** * Set an internal execution variable * @internal * @param name * @param value */ _setExecutionVariable(block, name, value) { this._executionVariables[this._getUniqueIdPrefixedName(block, name)] = value; } /** * Get an internal execution variable * @internal * @param name * @returns */ _getExecutionVariable(block, name, defaultValue) { if (this._hasExecutionVariable(block, name)) { return this._executionVariables[this._getUniqueIdPrefixedName(block, name)]; } else { return defaultValue; } } /** * Delete an internal execution variable * @internal * @param block * @param name */ _deleteExecutionVariable(block, name) { delete this._executionVariables[this._getUniqueIdPrefixedName(block, name)]; } /** * Check if an internal execution variable is defined * @internal * @param block * @param name * @returns */ _hasExecutionVariable(block, name) { return this._getUniqueIdPrefixedName(block, name) in this._executionVariables; } /** * Check if a connection value is defined * @internal * @param connectionPoint * @returns */ _hasConnectionValue(connectionPoint) { return connectionPoint.uniqueId in this._connectionValues; } /** * Set a connection value * @internal * @param connectionPoint * @param value */ _setConnectionValue(connectionPoint, value) { this._connectionValues[connectionPoint.uniqueId] = value; this.logger?.addLogItem({ time: Date.now(), className: this.getClassName(), uniqueId: this.uniqueId, action: "SetConnectionValue" /* FlowGraphAction.SetConnectionValue */, payload: { connectionPointId: connectionPoint.uniqueId, value, }, }); } /** * Set a connection value by key * @internal * @param key the key of the connection value * @param value the value of the connection */ _setConnectionValueByKey(key, value) { this._connectionValues[key] = value; } /** * Get a connection value * @internal * @param connectionPoint * @returns */ _getConnectionValue(connectionPoint) { this.logger?.addLogItem({ time: Date.now(), className: this.getClassName(), uniqueId: this.uniqueId, action: "GetConnectionValue" /* FlowGraphAction.GetConnectionValue */, payload: { connectionPointId: connectionPoint.uniqueId, value: this._connectionValues[connectionPoint.uniqueId], }, }); return this._connectionValues[connectionPoint.uniqueId]; } /** * Get the configuration * @internal * @param name * @param value */ get configuration() { return this._configuration; } /** * Check if there are any pending blocks in this context * @returns true if there are pending blocks */ get hasPendingBlocks() { return this._pendingBlocks.length > 0; } /** * Add a block to the list of blocks that have pending tasks. * @internal * @param block */ _addPendingBlock(block) { // check if block is already in the array if (this._pendingBlocks.includes(block)) { return; } this._pendingBlocks.push(block); // sort pending blocks by priority this._pendingBlocks.sort((a, b) => a.priority - b.priority); } /** * Remove a block from the list of blocks that have pending tasks. * @internal * @param block */ _removePendingBlock(block) { const index = this._pendingBlocks.indexOf(block); if (index !== -1) { this._pendingBlocks.splice(index, 1); } } /** * Clear all pending blocks. * @internal */ _clearPendingBlocks() { for (const block of this._pendingBlocks) { block._cancelPendingTasks(this); } this._pendingBlocks.length = 0; } /** * @internal * Function that notifies the node executed observable * @param node */ _notifyExecuteNode(node) { this.onNodeExecutedObservable.notifyObservers(node); this.logger?.addLogItem({ time: Date.now(), className: node.getClassName(), uniqueId: node.uniqueId, action: "ExecuteBlock" /* FlowGraphAction.ExecuteBlock */, }); } _notifyOnTick(framePayload) { // set the values as global variables this._setGlobalContextVariable("timeSinceStart", framePayload.timeSinceStart); this._setGlobalContextVariable("deltaTime", framePayload.deltaTime); // iterate the pending blocks and run each one's onFrame function for (const block of this._pendingBlocks) { block._executeOnTick?.(this); } } /** * @internal */ _increaseExecutionId() { this._executionId++; } /** * A monotonically increasing ID for each execution. * Incremented for every block executed. */ get executionId() { return this._executionId; } /** * Serializes a context * @param serializationObject the object to write the values in * @param valueSerializationFunction a function to serialize complex values */ serialize(serializationObject = {}, valueSerializationFunction = defaultValueSerializationFunction) { serializationObject.uniqueId = this.uniqueId; serializationObject._userVariables = {}; for (const key in this._userVariables) { valueSerializationFunction(key, this._userVariables[key], serializationObject._userVariables); } serializationObject._connectionValues = {}; for (const key in this._connectionValues) { valueSerializationFunction(key, this._connectionValues[key], serializationObject._connectionValues); } // serialize assets context, if not scene if (this.assetsContext !== this.getScene()) { serializationObject._assetsContext = { meshes: this.assetsContext.meshes.map((m) => m.id), materials: this.assetsContext.materials.map((m) => m.id), textures: this.assetsContext.textures.map((m) => m.name), animations: this.assetsContext.animations.map((m) => m.name), lights: this.assetsContext.lights.map((m) => m.id), cameras: this.assetsContext.cameras.map((m) => m.id), sounds: this.assetsContext.sounds?.map((m) => m.name), skeletons: this.assetsContext.skeletons.map((m) => m.id), particleSystems: this.assetsContext.particleSystems.map((m) => m.name), geometries: this.assetsContext.geometries.map((m) => m.id), multiMaterials: this.assetsContext.multiMaterials.map((m) => m.id), transformNodes: this.assetsContext.transformNodes.map((m) => m.id), }; } } /** * @returns the class name of the object. */ getClassName() { return "FlowGraphContext"; } } __decorate([ serialize() ], FlowGraphContext.prototype, "uniqueId", void 0); //# sourceMappingURL=flowGraphContext.js.map