UNPKG

pixi.js

Version:

<p align="center"> <a href="https://pixijs.com" target="_blank" rel="noopener noreferrer"> <img height="150" src="https://files.pixijs.download/branding/pixijs-logo-transparent-dark.svg?v=1" alt="PixiJS logo"> </a> </p> <br/> <p align="center">

1 lines 14.8 kB
{"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 | Filter[] | null | undefined)\n {\n if (!Array.isArray(value) && value) value = [value];\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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"}