"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PinchSceneRootUC = void 0;
exports.makePinchSceneRootUC = makePinchSceneRootUC;
const core_1 = require("@vived/core");
const core_2 = require("@vived/core");
const Babylon_1 = require("../../Babylon");
const Dispatcher_1 = require("../../Dispatcher");
const SceneRootEntity_1 = require("../Entities/SceneRootEntity");
class PinchSceneRootUC extends core_1.AppObjectUC {
}
exports.PinchSceneRootUC = PinchSceneRootUC;
PinchSceneRootUC.type = "PinchSceneRootUC";
PinchSceneRootUC.get = (appObjects) => (0, core_1.getSingletonComponent)(PinchSceneRootUC.type, appObjects);
function makePinchSceneRootUC(appObject) {
    return new PinchSceneRootImp(appObject);
}
class PinchSceneRootImp extends PinchSceneRootUC {
    getTouchCenter(t1, t2) {
        const delta = core_2.Vector2.Subtract(t2, t1);
        const halfDelta = core_2.Vector2.NewVectorOfLength(delta.unit, 0.5 * delta.magnitued);
        return core_2.Vector2.Add(t1, halfDelta);
    }
    getTouchDistance(t1, t2) {
        const delta = core_2.Vector2.Subtract(t2, t1);
        return delta.magnitued;
    }
    constructor(appObject) {
        super(appObject, PinchSceneRootUC.type);
        this.sensitivity = 0.01;
        this.previousDistanceBetweenTouches = 0;
        this.panPlane = core_2.ParametricPlane.XY();
        this.pickOffset = core_2.Vector3.Zero();
        this.initialScale = 0;
        this.initializePinch = (touchPos1, touchPos2) => {
            if (!this.sceneRoot)
                return;
            const transformNode = this.sceneRoot.transform;
            this.previousDistanceBetweenTouches = this.getTouchDistance(touchPos1, touchPos2);
            const touchCenter = this.getTouchCenter(touchPos1, touchPos2);
            const scenePick = (0, Babylon_1.scenePixelPick)(touchCenter, this.appObjects);
            const pickPoint = scenePick?.worldPickPoint ?? core_2.Vector3.Zero();
            const pickPlaneDirection = core_2.Vector3.Backward();
            this.panPlane = core_2.ParametricPlane.FromPointNormal(pickPoint, pickPlaneDirection);
            const pickRay = (0, Babylon_1.pixelToSceneRay)(touchCenter, this.appObjects);
            const planePick = this.panPlane.intersectLine(pickRay) ?? core_2.Vector3.Zero();
            this.pickOffset = transformNode.worldPointToLocal(planePick);
            this.initialScale = this.sceneRoot.scale;
        };
        this.doPinch = (touchPos1, touchPos2) => {
            if (!this.sceneRoot)
                return;
            const transformNode = this.sceneRoot.transform;
            const currentTouchDist = this.getTouchDistance(touchPos1, touchPos2);
            const touchDelta = currentTouchDist - this.previousDistanceBetweenTouches;
            const currentScale = this.sceneRoot.scale;
            const scaleDelta = touchDelta * this.sensitivity * currentScale;
            let newScale = currentScale + scaleDelta;
            if (newScale < this.sceneRoot.minScale) {
                newScale = this.sceneRoot.minScale;
            }
            else if (newScale > this.sceneRoot.maxScale) {
                newScale = this.sceneRoot.maxScale;
            }
            transformNode.worldScale = new core_2.Vector3(newScale, newScale, newScale);
            const touchCenter = this.getTouchCenter(touchPos1, touchPos2);
            const pickRay = (0, Babylon_1.pixelToSceneRay)(touchCenter, this.appObjects);
            const planePick = this.panPlane.intersectLine(pickRay) ?? core_2.Vector3.Zero();
            const globalOffset = transformNode.localPointToWorld(this.pickOffset);
            const delta = core_2.Vector3.Subtract(planePick, globalOffset);
            const currentWorldPos = transformNode.worldPosition;
            const newWorldPos = core_2.Vector3.Add(currentWorldPos, delta);
            transformNode.worldPosition = newWorldPos;
            this.previousDistanceBetweenTouches = currentTouchDist;
        };
        this.finishPinch = () => {
            if (this.initialScale === this.sceneRoot?.scale)
                return;
            (0, Dispatcher_1.dispatchStateChange)(this.appObjects);
        };
        this.sceneRoot = appObject.getComponent(SceneRootEntity_1.SceneRootEntity.type);
        if (!this.sceneRoot) {
            this.warn("PinchSceneRootUC UC has been added to an App Object that does not have a SceneRoot Entity");
            return;
        }
    }
}
//# sourceMappingURL=PinchSceneRoot.js.map