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 { Matrix4, Object3D, Quaternion, Vector3 } from "three";
import { isDevEnvironment } from "../../engine/debug/index.js";
import { serializable } from "../../engine/engine_serialization.js";
import { lookAtObject } from "../../engine/engine_three_utils.js";
import { ActionBuilder, BehaviorModel, TriggerBuilder, USDVec3 } from "../../engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js";
import { USDObject } from "../../engine-components/export/usdz/ThreeUSDZExporter.js";
import { Behaviour } from "../Component.js";
/**
 * LookAt behaviour makes the object look at a target object or the camera.
 * It can also invert the forward direction and keep the up direction.
 *
 * @summary Makes the object look at a target object or the camera
 * @category Interactivity, Everywhere Actions
 * @group Components
 */
export class LookAt extends Behaviour {
    /**
     * The target object to look at. If not set, the main camera will be used.
     */
    target;
    /**
     * Inverts the forward direction.
     */
    invertForward = false;
    /**
     * Keep the up direction.
     */
    keepUpDirection = true;
    /**
     * Copy the target rotation.
     */
    copyTargetRotation = false;
    static flipYQuat = new Quaternion().setFromAxisAngle(new Vector3(0, 1, 0), Math.PI);
    /** @internal */
    onBeforeRender() {
        let target = this.target;
        if (!target) {
            target = this.context.mainCamera;
            if (isDevEnvironment() && !this["__did_warn"]) {
                this["__did_warn"] = true;
                console.debug(`[LookAt] No target set on ${this.name}, using main camera as target.`);
            }
        }
        if (!target)
            return;
        let copyTargetRotation = this.copyTargetRotation;
        // Disable copy target rotation during VR/AR session: https://linear.app/needle/issue/NE-5634
        if (this.context.isInVR || this.context.isInPassThrough) {
            copyTargetRotation = false;
        }
        lookAtObject(this.gameObject, target, this.keepUpDirection, copyTargetRotation);
        if (this.invertForward)
            this.gameObject.quaternion.multiply(LookAt.flipYQuat);
    }
    /** @internal */
    createBehaviours(ext, model, _context) {
        if (model.uuid === this.gameObject.uuid) {
            let alignmentTarget = model;
            // not entirely sure why we need to do this - looks like LookAt with up vector doesn't work properly in
            // QuickLook, so we need to introduce an empty parent and rotate the model by 90° around Y
            if (this.keepUpDirection) {
                const parent = USDObject.createEmptyParent(model);
                alignmentTarget = parent;
                // rotate by 90° - counter-rotation on the parent makes sure 
                // that without Preliminary Behaviours it still looks right
                const flip = this.invertForward ? -1 : 1;
                parent.setMatrix(parent.getMatrix().multiply(new Matrix4().makeRotationZ(Math.PI / 2 * flip)));
                model.setMatrix(model.getMatrix().multiply(new Matrix4().makeRotationZ(-Math.PI / 2 * flip)));
            }
            const lookAt = new BehaviorModel("lookat " + this.name, TriggerBuilder.sceneStartTrigger(), ActionBuilder.lookAtCameraAction(alignmentTarget, undefined, this.invertForward ? USDVec3.back : USDVec3.forward, this.keepUpDirection ? USDVec3.up : USDVec3.zero));
            ext.addBehavior(lookAt);
        }
    }
}
__decorate([
    serializable(Object3D)
], LookAt.prototype, "target", void 0);
__decorate([
    serializable()
], LookAt.prototype, "invertForward", void 0);
__decorate([
    serializable()
], LookAt.prototype, "keepUpDirection", void 0);
__decorate([
    serializable()
], LookAt.prototype, "copyTargetRotation", void 0);
//# sourceMappingURL=LookAt.js.map