UNPKG

polygonjs-engine

Version:

node-based webgl 3D engine https://polygonjs.com

127 lines (109 loc) 3.49 kB
import {CoreGraphNode} from './CoreGraphNode'; import {CoreGraphNodeId} from './CoreGraph'; export type PostDirtyHook = (caller?: CoreGraphNode) => void; export class DirtyController { _dirty_count: number = 0; _dirty: boolean = true; _dirty_timestamp: number | undefined; _cached_successors: CoreGraphNode[] | undefined; _forbidden_trigger_nodes: CoreGraphNodeId[] | undefined; // hooks _post_dirty_hooks: PostDirtyHook[] | undefined; _post_dirty_hook_names: string[] | undefined; constructor(private node: CoreGraphNode) {} dispose() { this._cached_successors = undefined; this._post_dirty_hooks = undefined; this._post_dirty_hook_names = undefined; } isDirty(): boolean { return this._dirty === true; } dirtyTimestamp() { return this._dirty_timestamp; } dirtyCount(): number { return this._dirty_count; } addPostDirtyHook(name: string, method: PostDirtyHook) { this._post_dirty_hook_names = this._post_dirty_hook_names || []; this._post_dirty_hooks = this._post_dirty_hooks || []; if (!this._post_dirty_hook_names.includes(name)) { this._post_dirty_hook_names.push(name); this._post_dirty_hooks.push(method); } else { console.warn(`hook with name ${name} already exists`, this.node); } } removePostDirtyHook(name: string) { if (this._post_dirty_hook_names && this._post_dirty_hooks) { const index = this._post_dirty_hook_names.indexOf(name); if (index >= 0) { this._post_dirty_hook_names.splice(index, 1); this._post_dirty_hooks.splice(index, 1); } } } has_hook(name: string): boolean { if (this._post_dirty_hook_names) { return this._post_dirty_hook_names.includes(name); } return false; } removeDirtyState(): void { this._dirty = false; } set_forbidden_trigger_nodes(nodes: CoreGraphNode[]) { this._forbidden_trigger_nodes = nodes.map((n) => n.graphNodeId()); } set_dirty(original_trigger_graph_node?: CoreGraphNode | null, propagate?: boolean): void { if (propagate == null) { propagate = true; } if ( original_trigger_graph_node && this._forbidden_trigger_nodes && this._forbidden_trigger_nodes.includes(original_trigger_graph_node.graphNodeId()) ) { return; } if (original_trigger_graph_node == null) { original_trigger_graph_node = this.node; } this._dirty = true; this._dirty_timestamp = performance.now(); this._dirty_count += 1; this.run_post_dirty_hooks(original_trigger_graph_node); if (propagate === true) { this.set_successors_dirty(original_trigger_graph_node); } } run_post_dirty_hooks(original_trigger_graph_node?: CoreGraphNode) { if (this._post_dirty_hooks) { const cooker = this.node.scene().cooker; if (cooker.blocked) { cooker.enqueue(this.node, original_trigger_graph_node); } else { for (let hook of this._post_dirty_hooks) { hook(original_trigger_graph_node); } } } } set_successors_dirty(original_trigger_graph_node?: CoreGraphNode): void { const propagate = false; this._cached_successors = this._cached_successors || this.node.graphAllSuccessors(); for (let successor of this._cached_successors) { successor.dirtyController.set_dirty(original_trigger_graph_node, propagate); } } clear_successors_cache() { this._cached_successors = undefined; } clear_successors_cache_with_predecessors() { this.clear_successors_cache(); for (let predecessor of this.node.graphAllPredecessors()) { predecessor.dirtyController.clear_successors_cache(); } } }