import { AppObjectUC, Quaternion, Vector3 } from "@vived/core";
import { SceneRootEntity } from "../../SceneRoot/Entities/SceneRootEntity";
import { CalloutEntity } from "../Entities/CalloutEntity";
export class LookAtCameraUC extends AppObjectUC {
    static get(appObj) {
        return appObj.getComponent(this.type);
    }
}
LookAtCameraUC.type = "LookAtCameraUC";
export function makeLookAtCameraUC(appObject) {
    return new LookAtCameraUCIMP(appObject);
}
class LookAtCameraUCIMP extends LookAtCameraUC {
    get sceneRootEntity() {
        return this.getCachedSingleton(SceneRootEntity.type);
    }
    get callout() {
        return this.getCachedLocalComponent(CalloutEntity.type);
    }
    kickOffSlerping() {
        if (this.slerpInterval) {
            this.stopSlerping();
        }
        this.isSlerping = true;
        const transform = this.callout?.labelTransform;
        if (!transform)
            return;
        let previousError = Quaternion.AngleBetween(transform.worldRotation, this.targetQ).degrees;
        this.slerpInterval = setInterval(() => {
            const error = Quaternion.AngleBetween(transform.worldRotation, this.targetQ).degrees;
            if (error < 0.15) {
                this.stopSlerping();
                return;
            }
            const deltaError = error - previousError;
            if (deltaError === 0) {
                this.stopSlerping();
                return;
            }
            const kp = 0.05;
            const kd = 5;
            const pEffect = kp * error;
            const dEffect = kd * (deltaError / 10);
            const deltaAng = pEffect + dEffect;
            let slerpPercent = deltaAng / error;
            if (slerpPercent > 1) {
                slerpPercent = 1;
            }
            const slerpedQ = Quaternion.Slerp(transform.worldRotation, this.targetQ, slerpPercent);
            transform.worldRotation = slerpedQ;
            previousError = error;
        }, 10);
    }
    constructor(appObject) {
        super(appObject, LookAtCameraUC.type);
        this.cameraPos = new Vector3(0, 0, -0.6);
        this.targetQ = Quaternion.Identity();
        this.isSlerping = false;
        this.onChange = () => {
            if (!this.callout)
                return;
            const parent = this.callout.labelTransform.parent;
            if (!parent) {
                return;
            }
            const worldDir = Vector3.Subtract(this.cameraPos, this.callout.labelTransform.worldPosition);
            // const localDir = parent.worldDirectionToLocal(worldDir);
            const desiredQ = Quaternion.FromDirectionVector(worldDir);
            if (Quaternion.Close(this.targetQ, desiredQ)) {
                return;
            }
            this.targetQ = desiredQ;
            if (!this.isSlerping) {
                this.kickOffSlerping();
            }
        };
        this.stopSlerping = () => {
            if (this.callout) {
                this.callout.labelTransform.worldRotation = this.targetQ;
            }
            if (this.slerpInterval) {
                clearInterval(this.slerpInterval);
                this.slerpInterval = undefined;
            }
            this.isSlerping = false;
        };
        this.dispose = () => {
            super.dispose();
            this.sceneRootEntity?.removeChangeObserver(this.onChange);
        };
        this.sceneRootEntity?.addChangeObserver(this.onChange);
        this.callout?.addChangeObserver(this.onChange);
        this.onChange();
    }
}
//# sourceMappingURL=LookAtCameraUC.js.map