{"version":3,"file":"effectsMixin.mjs","sources":["../../../../src/scene/container/container-mixins/effectsMixin.ts"],"sourcesContent":["import { FilterEffect } from '../../../filters/FilterEffect';\nimport { MaskEffectManager } from '../../../rendering/mask/MaskEffectManager';\n\nimport type { Filter } from '../../../filters/Filter';\nimport type { Rectangle } from '../../../maths/shapes/Rectangle';\nimport type { MaskEffect } from '../../../rendering/mask/MaskEffectManager';\nimport type { Container } from '../Container';\nimport type { Effect } from '../Effect';\n\n/** @ignore */\nexport interface EffectsMixinConstructor\n{\n    /**\n     * The mask to apply, which can be a Container or null.\n     *\n     * If null, it clears the existing mask.\n     * @example\n     * ```ts\n     * // Set a mask\n     * sprite.setMask({\n     *     mask: graphics,\n     *     inverse: false,\n     * });\n     */\n    mask?: Mask;\n    setMask?: (options: Partial<MaskOptionsAndMask>) => void;\n    /**\n     * Sets the filters for the displayObject.\n     * Filters are visual effects that can be applied to any display object and its children.\n     *\n     * > [!IMPORTANT] This is a WebGL/WebGPU only feature and will be ignored by the canvas renderer.\n     * @example\n     * ```ts\n     * new Container({\n     *     filters: [new BlurFilter(2), new ColorMatrixFilter()],\n     * });\n     * ```\n     * @see {@link Filter} For filter base class\n     */\n    filters?: Filter | readonly Filter[];\n}\n\n/**\n * The Mask type represents different ways to mask a display object.\n * - A number represents a mask ID.\n * - A Container represents a mask object, such as a Graphics or Sprite.\n * - null indicates that no mask is applied.\n * @example\n * ```ts\n * // Using a Container as a mask\n * const maskContainer: Mask = new Graphics();\n * // Using a mask ID\n * const maskId: Mask = 123;\n * // No mask applied\n * const noMask: Mask = null;\n * ```\n * @category scene\n * @standard\n */\nexport type Mask = number | Container | null;\n\n/**\n * Options for configuring mask behavior on a display object.\n * @example\n * ```ts\n * // Basic mask inversion\n * sprite.setMask({\n *     mask: graphics,\n *     inverse: true\n * });\n * ```\n * @see {@link Container#setMask} For applying masks with options\n * @see {@link Container#mask} For basic masking\n * @category scene\n * @standard\n */\nexport interface MaskOptions\n{\n    /**\n     * Whether the mask should be inverted.\n     * When true, the masked area becomes transparent and the unmasked area becomes visible.\n     * @default false\n     * @example\n     * ```ts\n     * // Invert the mask\n     * sprite.setMask({\n     *     mask: graphics,\n     *     inverse: true\n     * });\n     * ```\n     */\n    inverse: boolean;\n}\n\n/**\n * MaskOptionsAndMask combines MaskOptions with a Mask for configuring masking behavior.\n * Used when setting up complex masking effects with additional options.\n * @example\n * ```ts\n * sprite.setMask({\n *     mask: graphics,\n *     inverse: true,\n * });\n *\n * // Clear existing mask\n * sprite.setMask({\n *     mask: null,\n *     inverse: false,\n * });\n * ```\n * @category scene\n * @standard\n * @see {@link Container#setMask} For applying masks\n * @see {@link MaskOptions} For base options\n */\nexport interface MaskOptionsAndMask extends MaskOptions\n{\n    /**\n     * The mask to apply, which can be a Container or null.\n     *\n     * If null, it clears the existing mask.\n     * @example\n     * ```ts\n     * // Set a mask\n     * sprite.setMask({\n     *     mask: graphics,\n     *     inverse: false,\n     * });\n     */\n    mask: Mask;\n}\n\n/**\n * The EffectsMixin interface provides methods and properties for managing effects\n * such as masks and filters on a display object.\n * It allows for adding, removing, and configuring effects, as well as setting a mask for the display object.\n * @category scene\n * @advanced\n */\nexport interface EffectsMixin extends Required<EffectsMixinConstructor>\n{\n    /** @private */\n    _maskEffect?: MaskEffect;\n    /** @private */\n    _maskOptions?: MaskOptions;\n    /** @private */\n    _filterEffect?: FilterEffect,\n    /** @private */\n    _markStructureAsChanged(): void;\n\n    /**\n     * The area the filter is applied to. This is used as an optimization to define a specific region\n     * for filter effects instead of calculating the display object bounds each frame.\n     *\n     * > [!NOTE]\n     * > Setting this to a custom Rectangle allows you to define a specific area for filter effects,\n     * > which can improve performance by avoiding expensive bounds calculations.\n     * @example\n     * ```ts\n     * // Set specific filter area\n     * container.filterArea = new Rectangle(0, 0, 100, 100);\n     *\n     * // Optimize filter region\n     * const screen = app.screen;\n     * container.filterArea = new Rectangle(\n     *     screen.x,\n     *     screen.y,\n     *     screen.width,\n     *     screen.height\n     * );\n     * ```\n     * @see {@link Container#filters} For applying filters\n     * @see {@link Rectangle} For area definition\n     */\n    filterArea?: Rectangle,\n    /**\n     * todo Needs docs\n     * @advanced\n     */\n    effects?: Effect[];\n    /**\n     * todo Needs docs.\n     * @param {Effect} effect - The effect to add.\n     * @ignore\n     */\n    addEffect(effect: Effect): void;\n    /**\n     * todo Needs docs.\n     * @param {Effect} effect - The effect to remove.\n     * @ignore\n     */\n    removeEffect(effect: Effect): void;\n    /**\n     * Used to set mask and control mask options on a display object.\n     * Allows for more detailed control over masking behavior compared to the mask property.\n     * @example\n     * ```ts\n     * import { Graphics, Sprite } from 'pixi.js';\n     *\n     * // Create a circular mask\n     * const graphics = new Graphics()\n     *     .beginFill(0xFF3300)\n     *     .drawCircle(100, 100, 50)\n     *     .endFill();\n     *\n     * // Apply mask with options\n     * sprite.setMask({\n     *     mask: graphics,\n     *     inverse: true, // Create a hole effect\n     * });\n     *\n     * // Clear existing mask\n     * sprite.setMask({ mask: null });\n     * ```\n     * @param {Partial<MaskOptionsAndMask>} options - Configuration options for the mask\n     * @see {@link Container#mask} For simple masking\n     * @see {@link MaskOptionsAndMask} For full options API\n     */\n    setMask(options: Partial<MaskOptionsAndMask>): void;\n    /**\n     * Sets a mask for the displayObject. A mask is an object that limits the visibility of an\n     * object to the shape of the mask applied to it.\n     *\n     * > [!IMPORTANT] In PixiJS a regular mask must be a {@link Graphics} or a {@link Sprite} object.\n     * > This allows for much faster masking in canvas as it utilities shape clipping.\n     * > Furthermore, a mask of an object must be in the subtree of its parent.\n     * > Otherwise, `getLocalBounds` may calculate incorrect bounds, which makes the container's width and height wrong.\n     *\n     * For sprite mask both alpha and red channel are used. Black mask is the same as transparent mask.\n     * @example\n     * ```ts\n     * // Apply mask to sprite\n     * const sprite = new Sprite(texture);\n     * sprite.mask = graphics;\n     *\n     * // Remove mask\n     * sprite.mask = null;\n     * ```\n     * @see {@link Graphics} For creating mask shapes\n     * @see {@link Sprite} For texture-based masks\n     * @see {@link Container#setMask} For advanced mask options\n     */\n    mask: Mask;\n    /**\n     * Sets the filters for the displayObject.\n     * Filters are visual effects that can be applied to any display object and its children.\n     *\n     * > [!IMPORTANT] This is a WebGL/WebGPU only feature and will be ignored by the canvas renderer.\n     * @example\n     * ```ts\n     * // Add a single filter\n     * sprite.filters = new BlurFilter(2);\n     *\n     * // Apply multiple filters\n     * container.filters = [\n     *     new BlurFilter(2),\n     *     new ColorMatrixFilter(),\n     * ];\n     *\n     * // Remove filters\n     * sprite.filters = null;\n     * ```\n     * @see {@link Filter} For filter base class\n     */\n    set filters(value: Filter | Filter[] | null | undefined);\n    get filters(): readonly Filter[];\n}\n\n/** @internal */\nexport const effectsMixin: Partial<Container> = {\n    _maskEffect: null,\n    _maskOptions: {\n        inverse: false,\n    },\n    _filterEffect: null,\n\n    effects: [],\n\n    _markStructureAsChanged()\n    {\n        const renderGroup = this.renderGroup || this.parentRenderGroup;\n\n        if (renderGroup)\n        {\n            renderGroup.structureDidChange = true;\n        }\n    },\n\n    addEffect(effect: Effect)\n    {\n        const index = this.effects.indexOf(effect);\n\n        if (index !== -1) return; // already exists!\n\n        this.effects.push(effect);\n\n        this.effects.sort((a, b) => a.priority - b.priority);\n\n        this._markStructureAsChanged();\n\n        // if (this.renderGroup)\n        // {\n        //     this.renderGroup.structureDidChange = true;\n        // }\n\n        this._updateIsSimple();\n    },\n\n    removeEffect(effect: Effect)\n    {\n        const index = this.effects.indexOf(effect);\n\n        if (index === -1) return; // already exists!\n\n        this.effects.splice(index, 1);\n\n        this._markStructureAsChanged();\n\n        this._updateIsSimple();\n    },\n\n    set mask(value: Mask)\n    {\n        const effect = this._maskEffect;\n\n        if (effect?.mask === value) return;\n\n        if (effect)\n        {\n            this.removeEffect(effect);\n\n            MaskEffectManager.returnMaskEffect(effect);\n\n            this._maskEffect = null;\n        }\n\n        if (value === null || value === undefined) return;\n\n        this._maskEffect = MaskEffectManager.getMaskEffect(value);\n\n        this.addEffect(this._maskEffect);\n    },\n    get mask(): unknown\n    {\n        return this._maskEffect?.mask;\n    },\n\n    setMask(options: Partial<MaskOptionsAndMask>)\n    {\n        this._maskOptions = {\n            ...this._maskOptions,\n            ...options,\n        };\n\n        if (options.mask)\n        {\n            this.mask = options.mask;\n        }\n\n        this._markStructureAsChanged();\n    },\n\n    set filters(value: Filter | readonly Filter[] | null | undefined)\n    {\n        if (!Array.isArray(value) && value) value = ([value] as Filter[]);\n\n        const effect = this._filterEffect ||= new FilterEffect();\n\n        // Ignore the Filter type\n        value = value as Filter[] | null | undefined;\n\n        const hasFilters = value?.length > 0;\n        const hadFilters = effect.filters?.length > 0;\n\n        const didChange = hasFilters !== hadFilters;\n\n        // Clone the filters array so we don't freeze the user-input\n        value = Array.isArray(value) ? value.slice(0) : value;\n\n        // Ensure filters are immutable via filters getter\n        effect.filters = Object.freeze(value);\n\n        if (didChange)\n        {\n            if (hasFilters)\n            {\n                this.addEffect(effect);\n            }\n            else\n            {\n                this.removeEffect(effect);\n\n                // sets the empty array...\n                effect.filters = value ?? null;\n            }\n        }\n    },\n    get filters(): readonly Filter[]\n    {\n        return this._filterEffect?.filters;\n    },\n\n    set filterArea(value: Rectangle)\n    {\n        this._filterEffect ||= new FilterEffect();\n\n        this._filterEffect.filterArea = value;\n    },\n    get filterArea(): Rectangle\n    {\n        return this._filterEffect?.filterArea;\n    },\n\n} as Container;\n"],"names":[],"mappings":"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"}