{"version":3,"file":"CubeTexture.mjs","sources":["../../../../../src/rendering/renderers/shared/texture/CubeTexture.ts"],"sourcesContent":["import EventEmitter from 'eventemitter3';\nimport { Cache } from '../../../../assets/cache/Cache';\nimport { uid } from '../../../../utils/data/uid';\nimport { CubeTextureSource } from './sources/CubeTextureSource';\nimport { type TextureSource } from './sources/TextureSource';\nimport { Texture } from './Texture';\n\nimport type { CubeTextureFaces, CubeTextureSourceOptions } from './sources/CubeTextureSource';\nimport type { BindableTexture, TextureSourceLike } from './Texture';\n\ntype CubeTextureFaceInputs = {\n    left: TextureSourceLike | BindableTexture;\n    right: TextureSourceLike | BindableTexture;\n    top: TextureSourceLike | BindableTexture;\n    bottom: TextureSourceLike | BindableTexture;\n    front: TextureSourceLike | BindableTexture;\n    back: TextureSourceLike | BindableTexture;\n};\n\ntype CubeTextureFromOptions = Omit<CubeTextureSourceOptions, 'faces'> & { faces: CubeTextureFaceInputs };\n\nconst faceKeys = ['left', 'right', 'top', 'bottom', 'front', 'back'] as const;\n\nfunction getCubeCacheKey(faceIds: CubeTextureFaces<string>, options: Omit<CubeTextureSourceOptions, 'faces'>): string\n{\n    const opts = options ? { ...(options as any) } : {};\n\n    // Don't include label in the cache key.\n    delete opts.label;\n\n    const optKeys = Object.keys(opts).sort();\n    const optPart = optKeys.length\n        ? `|${optKeys.map((k) => `${k}=${String(opts[k])}`).join('&')}`\n        : '';\n\n    // Note: Order is explicit and stable.\n    const facesPart = faceKeys.map((k) => faceIds[k]).join(',');\n\n    return `cube:${facesPart}${optPart}`;\n}\n\n/**\n * The options that can be passed to a new {@link CubeTexture}.\n * @category rendering\n * @advanced\n */\nexport interface CubeTextureOptions\n{\n    /** The underlying cube texture source. */\n    source: CubeTextureSource;\n    /** Optional label, for debugging. */\n    label?: string;\n}\n\n/**\n * A cube texture that can be bound to shaders (samplerCube / texture_cube).\n *\n * This is a lightweight wrapper around a {@link CubeTextureSource}.\n * @example\n * Load 6 images and create a cube texture (paths are just examples):\n *\n * ```ts\n * import { Assets, CubeTexture } from 'pixi.js';\n *\n * await Assets.load([\n *   'px.png', 'nx.png',\n *   'py.png', 'ny.png',\n *   'pz.png', 'nz.png',\n * ]);\n *\n * // IMPORTANT: string ids must already be in the cache (e.g. after Assets.load)\n * const cube = CubeTexture.from({\n *   faces: {\n *     right: 'px.png',  // +X\n *     left: 'nx.png',   // -X\n *     top: 'py.png',    // +Y\n *     bottom: 'ny.png', // -Y\n *     front: 'pz.png',  // +Z\n *     back: 'nz.png',   // -Z\n *   },\n *   label: 'skybox',\n * });\n * ```\n * @example\n * Bind to a shader (resources differ between WebGL and WebGPU, but the cube texture binding stays the same):\n *\n * ```ts\n * const shader = Shader.from({\n *   gl: { fragment: `uniform samplerCube uCube;` },\n *   gpu: { fragment: { source: `@group(0) @binding(0) var uCube : texture_cube<f32>;` } },\n *   resources: {\n *     uCube: cube.source,\n *     uSampler: cube.source.style,\n *   },\n * });\n * ```\n * @category rendering\n * @advanced\n */\nexport class CubeTexture extends EventEmitter<{ destroy: CubeTexture }> implements BindableTexture\n{\n    /** unique id for this cube texture */\n    public readonly uid: number = uid('cubeTexture');\n\n    /** Has the texture been destroyed? */\n    public destroyed = false;\n\n    /** The underlying cube texture source. */\n    public readonly source: CubeTextureSource;\n\n    /** Optional label for debugging. */\n    public label?: string;\n\n    constructor(options: CubeTextureOptions)\n    {\n        super();\n\n        const { label, source } = options;\n\n        this.label = label;\n\n        this.source = source;\n\n        this.source.label = this.label ?? this.source.label;\n    }\n\n    /**\n     * Convenience factory for creating a cube texture from a {@link CubeTextureSource}.\n     * @param options - A cube texture source.\n     * @param skipCache - Unused for this overload.\n     */\n    public static from(options: CubeTextureSource, skipCache?: boolean): CubeTexture;\n    /**\n     * Convenience factory for creating a cube texture from 6 face inputs.\n     *\n     * Face inputs are converted to {@link Texture} via {@link Texture.from}. This does **not** load resources;\n     * string ids must already be present in the cache (e.g. after `Assets.load`).\n     * @example\n     * ```ts\n     * const cube = CubeTexture.from({\n     *   faces: {\n     *     right: 'px.png',\n     *     left: 'nx.png',\n     *     top: 'py.png',\n     *     bottom: 'ny.png',\n     *     front: 'pz.png',\n     *     back: 'nz.png',\n     *   },\n     * });\n     * ```\n     * @param options - Options including the 6 face inputs.\n     * @param skipCache - Skip caching the resulting {@link CubeTexture} when all faces are string ids.\n     */\n    public static from(options: CubeTextureFromOptions, skipCache?: boolean): CubeTexture;\n    public static from(options: CubeTextureSource | CubeTextureFromOptions, skipCache = false): CubeTexture\n    {\n        if (options instanceof CubeTextureSource)\n        {\n            return new CubeTexture({ source: options });\n        }\n\n        const { faces, ...sourceOptions } = options;\n\n        // Cache only when faces are string ids (matches Texture.from string semantics).\n        let cacheKey: string = null;\n\n        const isFaceIds = faceKeys.every((key) => typeof faces[key] === 'string');\n\n        if (!skipCache && isFaceIds)\n        {\n            cacheKey = getCubeCacheKey(faces as unknown as CubeTextureFaces<string>, sourceOptions);\n\n            if (Cache.has(cacheKey))\n            {\n                return Cache.get(cacheKey);\n            }\n        }\n\n        const toTexture = (input: TextureSourceLike | BindableTexture): Texture =>\n        {\n            if ((input as any).isTexture) return input as Texture;\n\n            return Texture.from(input as TextureSourceLike);\n        };\n\n        const faceSources = {} as CubeTextureFaces<TextureSource>;\n\n        for (const key of faceKeys)\n        {\n            faceSources[key] = toTexture(faces[key]).source;\n        }\n\n        const cubeTexture = new CubeTexture({\n            source: new CubeTextureSource({\n                ...(sourceOptions as Omit<CubeTextureSourceOptions, 'faces'>),\n                faces: faceSources,\n            }),\n            label: sourceOptions.label,\n        });\n\n        if (cacheKey)\n        {\n            Cache.set(cacheKey, cubeTexture);\n\n            cubeTexture.once('destroy', () =>\n            {\n                if (Cache.has(cacheKey))\n                {\n                    Cache.remove(cacheKey);\n                }\n            });\n        }\n\n        return cubeTexture;\n    }\n\n    /**\n     * Destroy this CubeTexture.\n     * @param destroySource - If true, destroys the underlying {@link CubeTextureSource}.\n     */\n    public destroy(destroySource = false): void\n    {\n        if (this.destroyed) return;\n\n        this.destroyed = true;\n\n        if (destroySource)\n        {\n            this.source.destroy();\n        }\n\n        this.emit('destroy', this);\n        this.removeAllListeners();\n    }\n}\n\n"],"names":[],"mappings":"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"}