var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { DoubleSide, Mesh, MeshBasicMaterial, PerspectiveCamera, PlaneGeometry, Scene, ShaderLib, ShaderMaterial, Texture, UniformsUtils, Vector4, } from "three";
import { serializable } from "../../engine/engine_serialization_decorator.js";
import { getParam } from "../../engine/engine_utils.js";
import { InternalScreenshotUtils } from "../../engine/engine_utils_screenshot.js";
import { updateTextureFromXRFrame } from "../../engine/engine_utils_screenshot.xr.js";
import { RGBAColor } from "../../engine/js-extensions/index.js";
import { Behaviour } from "../Component.js";
const debug = getParam("debugarcamera");
/**
 * WebARCameraBackground is a component that allows to display the camera feed as a background in an AR session to more easily blend the real world with the virtual world or applying effects to the camera feed.
 *
 * @category XR
 * @group Components
 */
export class WebARCameraBackground extends Behaviour {
    /** @internal */
    onBeforeXR(_mode, args) {
        if (_mode === "immersive-ar") {
            args.optionalFeatures = args.optionalFeatures || [];
            args.optionalFeatures.push('camera-access');
            if (debug)
                console.warn("Requesting camera-access");
        }
    }
    /** @internal */
    onEnterXR(_args) {
        if (_args.xr.mode === "immersive-ar") {
            if (this.backgroundPlane) {
                this.context.scene.add(this.backgroundPlane);
                this.backgroundPlane.visible = false;
            }
            if (this.backgroundPlane)
                this.context.scene.add(this.backgroundPlane);
            this.context.pre_render_callbacks.push(this.preRender);
        }
    }
    /** @internal */
    onLeaveXR(_args) {
        if (this.backgroundPlane)
            this.backgroundPlane.removeFromParent();
        const i = this.context.pre_render_callbacks.indexOf(this.preRender);
        if (i >= 0)
            this.context.pre_render_callbacks.splice(i, 1);
    }
    /**
     * The tint color of the camera feed
     */
    backgroundTint = new RGBAColor(1, 1, 1, 1);
    get background() {
        return this.backgroundPlane;
    }
    backgroundPlane;
    threeTexture;
    forceTextureInitialization = function () {
        const material = new MeshBasicMaterial();
        const geometry = new PlaneGeometry();
        const scene = new Scene();
        scene.add(new Mesh(geometry, material));
        const camera = new PerspectiveCamera();
        return function forceTextureInitialization(renderer, texture) {
            material.map = texture;
            renderer.render(scene, camera);
            if (debug)
                console.warn("Force texture initialization");
        };
    }();
    /** @internal */
    preRender = () => {
        if (!this || !this.gameObject)
            return;
        const xr = this.context.renderer.xr;
        const frame = xr.getFrame();
        if (frame) {
            // We're generating a new texture here, and force three to initialize it
            // from https://stackoverflow.com/a/55084367 to inject a custom texture into three.js
            if (!this.threeTexture && this.context.renderer) {
                this.threeTexture = new Texture();
                this.forceTextureInitialization(this.context.renderer, this.threeTexture);
            }
            // simple mesh and fullscreen shader to display the camera texture
            // from three: WebGLBackground
            if (this.backgroundPlane === undefined) {
                const tint = this.backgroundTint;
                this.backgroundPlane = InternalScreenshotUtils.makeFullscreenPlane({
                    material: new ShaderMaterial({
                        name: 'BackgroundMaterial',
                        uniforms: {
                            ...UniformsUtils.clone(ShaderLib.background.uniforms),
                            tint: { value: new Vector4(tint.r, tint.g, tint.b, tint.a) },
                        },
                        vertexShader: ShaderLib.background.vertexShader,
                        fragmentShader: backgroundFragment,
                        side: DoubleSide,
                        depthTest: false,
                        depthWrite: false,
                        fog: false
                    })
                });
            }
            if (this.backgroundPlane.parent !== this.scene)
                this.scene.add(this.backgroundPlane);
            if (this.backgroundPlane.material instanceof ShaderMaterial)
                this.backgroundPlane.material.uniforms.tint.value.set(this.backgroundTint.r, this.backgroundTint.g, this.backgroundTint.b, this.backgroundTint.a);
            // WebXR Raw Camera Access - 
            // we composite the camera texture into the scene background by rendering it first.
            this.updateFromFrame();
        }
    };
    /** @internal */
    onBeforeRender(_frame) {
        this.updateFromFrame();
    }
    updateFromFrame() {
        if (!this.threeTexture)
            return;
        if (this.context.xr?.mode === "immersive-ar") {
            updateTextureFromXRFrame(this.context.renderer, this.threeTexture);
            this.setTexture(this.threeTexture);
        }
    }
    setTexture(texture) {
        if (!this.backgroundPlane)
            return;
        this.threeTexture = texture;
        //@ts-ignore
        this.backgroundPlane.setTexture(this.threeTexture);
        this.backgroundPlane.visible = true;
    }
}
__decorate([
    serializable(RGBAColor)
], WebARCameraBackground.prototype, "backgroundTint", void 0);
const backgroundFragment = /* glsl */ `
uniform sampler2D t2D;
uniform vec4 tint;

varying vec2 vUv;

void main() {

    vec4 texColor = texture2D( t2D, vUv );
    texColor.w = 1.0;

    // inline sRGB decode
    texColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );

    gl_FragColor = texColor * tint;

    #include <tonemapping_fragment>
    #include <colorspace_fragment>
}
`;
//# sourceMappingURL=WebARCameraBackground.js.map