{"version":3,"file":"BlendModePipe.mjs","sources":["../../../../../src/rendering/renderers/shared/blendModes/BlendModePipe.ts"],"sourcesContent":["import { extensions, ExtensionType } from '../../../../extensions/Extensions';\nimport { FilterEffect } from '../../../../filters/FilterEffect';\nimport { warn } from '../../../../utils/logging/warn';\n\nimport type { BlendModeFilter } from '../../../../filters/blend-modes/BlendModeFilter';\nimport type { FilterInstruction } from '../../../../filters/FilterSystem';\nimport type { Renderer } from '../../types';\nimport type { Instruction } from '../instructions/Instruction';\nimport type { InstructionSet } from '../instructions/InstructionSet';\nimport type { InstructionPipe } from '../instructions/RenderPipe';\nimport type { Renderable } from '../Renderable';\nimport type { BLEND_MODES } from '../state/const';\n\ninterface AdvancedBlendInstruction extends Instruction\n{\n    renderPipeId: 'blendMode',\n    blendMode: BLEND_MODES,\n    activeBlend: Renderable[],\n}\n\n// class map\nconst BLEND_MODE_FILTERS: Partial<Record<BLEND_MODES, new () => BlendModeFilter>> = {} as const;\n\nextensions.handle(ExtensionType.BlendMode, (value) =>\n{\n    if (!value.name)\n    {\n        throw new Error('BlendMode extension must have a name property');\n    }\n    BLEND_MODE_FILTERS[value.name as BLEND_MODES] = value.ref;\n}, (value) =>\n{\n    delete BLEND_MODE_FILTERS[value.name as BLEND_MODES];\n});\n\n/**\n * This Pipe handles the blend mode switching of the renderer.\n * It will insert instructions into the {@link renderers.InstructionSet} to switch the blend mode according to the\n * blend modes of the scene graph.\n *\n * This pipe is were wwe handle Advanced blend modes. Advanced blend modes essentially wrap the renderables\n * in a filter that applies the blend mode.\n *\n * You only need to use this class if you are building your own render instruction set rather than letting PixiJS build\n * the instruction set for you by traversing the scene graph\n * @memberof rendering\n */\nexport class BlendModePipe implements InstructionPipe<AdvancedBlendInstruction>\n{\n    /** @ignore */\n    public static extension = {\n        type: [\n            ExtensionType.WebGLPipes,\n            ExtensionType.WebGPUPipes,\n            ExtensionType.CanvasPipes,\n        ],\n        name: 'blendMode',\n    } as const;\n\n    private _renderer: Renderer;\n\n    private _renderableList: Renderable[];\n    private _activeBlendMode: BLEND_MODES;\n\n    private _isAdvanced = false;\n\n    private _filterHash: Partial<Record<BLEND_MODES, FilterEffect>> = Object.create(null);\n\n    constructor(renderer: Renderer)\n    {\n        this._renderer = renderer;\n    }\n\n    /**\n     * This ensures that a blendMode switch is added to the instruction set if the blend mode has changed.\n     * @param renderable - The renderable we are adding to the instruction set\n     * @param blendMode - The blend mode of the renderable\n     * @param instructionSet - The instruction set we are adding to\n     */\n    public setBlendMode(renderable: Renderable, blendMode: BLEND_MODES, instructionSet: InstructionSet)\n    {\n        if (this._activeBlendMode === blendMode)\n        {\n            if (this._isAdvanced) this._renderableList.push(renderable);\n\n            return;\n        }\n\n        this._activeBlendMode = blendMode;\n\n        if (this._isAdvanced)\n        {\n            this._endAdvancedBlendMode(instructionSet);\n        }\n\n        this._isAdvanced = !!BLEND_MODE_FILTERS[blendMode];\n\n        if (this._isAdvanced)\n        {\n            this._beginAdvancedBlendMode(instructionSet);\n\n            this._renderableList.push(renderable);\n        }\n    }\n\n    private _beginAdvancedBlendMode(instructionSet: InstructionSet)\n    {\n        this._renderer.renderPipes.batch.break(instructionSet);\n\n        const blendMode = this._activeBlendMode;\n\n        if (!BLEND_MODE_FILTERS[blendMode as keyof typeof BLEND_MODE_FILTERS])\n        {\n            // #if _DEBUG\n            warn(`Unable to assign BlendMode: '${blendMode}'. `\n            + `You may want to include: import 'pixi.js/advanced-blend-modes'`);\n            // #endif\n\n            return;\n        }\n\n        let filterEffect = this._filterHash[blendMode];\n\n        // this does need an execute?\n        if (!filterEffect)\n        {\n            filterEffect = this._filterHash[blendMode] = new FilterEffect();\n\n            filterEffect.filters = [new BLEND_MODE_FILTERS[blendMode as keyof typeof BLEND_MODE_FILTERS]()];\n        }\n\n        const instruction: FilterInstruction = {\n            renderPipeId: 'filter',\n            action: 'pushFilter',\n            renderables: [],\n            filterEffect,\n            canBundle: false,\n        };\n\n        this._renderableList = instruction.renderables;\n        instructionSet.add(instruction);\n    }\n\n    private _endAdvancedBlendMode(instructionSet: InstructionSet)\n    {\n        this._renderableList = null;\n        this._renderer.renderPipes.batch.break(instructionSet);\n\n        instructionSet.add({\n            renderPipeId: 'filter',\n            action: 'popFilter',\n            canBundle: false,\n        });\n    }\n\n    /**\n     * called when the instruction build process is starting this will reset internally to the default blend mode\n     * @internal\n     * @ignore\n     */\n    public buildStart()\n    {\n        this._isAdvanced = false;\n    }\n\n    /**\n     * called when the instruction build process is finished, ensuring that if there is an advanced blend mode\n     * active, we add the final render instructions added to the instruction set\n     * @param instructionSet - The instruction set we are adding to\n     * @internal\n     * @ignore\n     */\n    public buildEnd(instructionSet: InstructionSet)\n    {\n        if (this._isAdvanced)\n        {\n            this._endAdvancedBlendMode(instructionSet);\n        }\n    }\n\n    /**\n     * @internal\n     * @ignore\n     */\n    public destroy()\n    {\n        this._renderer = null;\n        this._renderableList = null;\n\n        for (const i in this._filterHash)\n        {\n            this._filterHash[i as BLEND_MODES].destroy();\n        }\n\n        this._filterHash = null;\n    }\n}\n"],"names":[],"mappings":"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"}