/*!
 * Copyright (c) 2026 Vertex Software LLC. All rights reserved.
 */
import { r as registerInstance, h, H as Host, a as getElement } from './index-EpnuuCxl.js';
import { v as vector3, m as matrix4, q as quaternion, r as ray, a as angle } from './bundle-DfdVaPrt.js';
import { w as writeDOM, r as readDOM } from './stencil-CEl7wGvE.js';
import { M as MeshPoints, R as ReglComponent, r as regl, s as shapeBuilder, T as TriangleMesh, c as computeArrowNdcValues, a as Mesh, A as AxisLine, b as axisPositions } from './regl-component-C-oZktn7.js';
import './_commonjsHelpers-CG9AChtV.js';
import './bundle-DLfw87TV.js';
import './util-BrZtfp84.js';
import './streamAttributes-B6xi3kRV.js';
import './bundle-CLE0fYge.js';
import './entities-BAhfr1Nx.js';
import './viewport-DbTg_ax4.js';

function parseCssColorValue(styles, property) {
    return styles.getPropertyValue(property).trim().replace(/["']*/g, '');
}

function computePlaneNdcValues(transform, camera, direction, planeSize) {
    const transformedDirection = vector3.transformMatrix(direction, matrix4.makeRotation(quaternion.fromMatrixRotation(transform)));
    const position = vector3.fromMatrixPosition(transform);
    const worldX = Math.abs(vector3.dot(transformedDirection, vector3.up())) === 1
        ? vector3.left()
        : vector3.normalize(vector3.cross(transformedDirection, vector3.up()));
    const worldY = vector3.normalize(vector3.cross(worldX, transformedDirection));
    const xRay = ray.create({
        origin: position,
        direction: worldX,
    });
    const yRay = ray.create({
        origin: position,
        direction: worldY,
    });
    const bottomLeft = vector3.rotateAboutAxis(angle.toRadians(45), ray.at(xRay, -planeSize), transformedDirection, position);
    const topLeft = vector3.rotateAboutAxis(angle.toRadians(45), ray.at(yRay, -planeSize), transformedDirection, position);
    const bottomRight = vector3.rotateAboutAxis(angle.toRadians(45), ray.at(yRay, planeSize), transformedDirection, position);
    const topRight = vector3.rotateAboutAxis(angle.toRadians(45), ray.at(xRay, planeSize), transformedDirection, position);
    const world = [bottomLeft, topLeft, topRight, bottomRight];
    return new MeshPoints(!isNaN(worldX.x), [bottomLeft, topLeft, topRight, bottomRight], world.map((v) => vector3.transformMatrix(v, camera.projectionViewMatrix)), (vector) => vector3.distance(position, vector));
}

function computePointNdcValues(transform, camera, direction, rectangleSize) {
    const transformedDirection = vector3.transformMatrix(direction, matrix4.makeRotation(quaternion.fromMatrixRotation(transform)));
    const position = vector3.fromMatrixPosition(transform);
    const worldX = vector3.normalize(vector3.cross(transformedDirection, vector3.normalize(camera.viewVector)));
    const worldY = vector3.normalize(vector3.cross(transformedDirection, worldX));
    const xRay = ray.create({
        origin: position,
        direction: worldX,
    });
    const yRay = ray.create({
        origin: position,
        direction: worldY,
    });
    const bottomLeft = ray.at(xRay, -rectangleSize);
    const topLeft = ray.at(yRay, -rectangleSize);
    const bottomRight = ray.at(yRay, rectangleSize);
    const topRight = ray.at(xRay, rectangleSize);
    const bottomLeftRotated = vector3.rotateAboutAxis(angle.toRadians(45), bottomLeft, transformedDirection, position);
    const topLeftRotated = vector3.rotateAboutAxis(angle.toRadians(45), topLeft, transformedDirection, position);
    const bottomRightRotated = vector3.rotateAboutAxis(angle.toRadians(45), bottomRight, transformedDirection, position);
    const topRightRotated = vector3.rotateAboutAxis(angle.toRadians(45), topRight, transformedDirection, position);
    const world = [
        bottomLeft,
        bottomLeftRotated,
        topLeft,
        topLeftRotated,
        topRight,
        topRightRotated,
        bottomRight,
        bottomRightRotated,
    ];
    return new MeshPoints(!isNaN(worldX.x), world, world.map((v) => vector3.transformMatrix(v, camera.projectionViewMatrix)), (vector) => vector3.distance(position, vector));
}

// The default amount to scale the computed `triangleSize` by when
// computing the points for the hit position indicator.
const DEFAULT_POINT_SIZE_SCALAR = 0.4;
// The default amount to scale the computed `triangleSize` by when
// computing the points for the hit plane indicator.
const DEFAULT_PLANE_SIZE_SCALAR = 5;
const DEFAULT_PLANE_OPACITY = 0.75;
class HitIndicator extends ReglComponent {
    constructor(canvasElement, colors = {}, opacities = {}) {
        super(canvasElement);
        this.arrowFillColor = colors.arrow;
        this.planeFillColor = colors.plane;
        this.outlineColor = colors.outline;
        this.planeOpacity = opacities.plane;
    }
    updateTransformAndNormal(transform, normal) {
        var _a;
        this.transform = transform;
        this.normal = normal;
        if (transform != null && normal != null && this.frame != null) {
            this.updateAndDraw();
        }
        else {
            this.clear();
            (_a = this.reglFrameDisposable) === null || _a === void 0 ? void 0 : _a.cancel();
            this.reglFrameDisposable = undefined;
        }
    }
    updateColors(colors) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j;
        this.arrowFillColor = (_a = colors.arrow) !== null && _a !== void 0 ? _a : this.arrowFillColor;
        this.planeFillColor = (_b = colors.plane) !== null && _b !== void 0 ? _b : this.planeFillColor;
        this.outlineColor = (_c = colors.outline) !== null && _c !== void 0 ? _c : this.outlineColor;
        (_d = this.arrow) === null || _d === void 0 ? void 0 : _d.updateFillColor(this.arrowFillColor);
        (_e = this.plane) === null || _e === void 0 ? void 0 : _e.updateFillColor(this.planeFillColor);
        (_f = this.arrow) === null || _f === void 0 ? void 0 : _f.updateOutlineColor(this.outlineColor);
        (_g = this.plane) === null || _g === void 0 ? void 0 : _g.updateOutlineColor(this.outlineColor);
        (_h = this.point) === null || _h === void 0 ? void 0 : _h.updateOutlineColor(this.outlineColor);
        (_j = this.axis) === null || _j === void 0 ? void 0 : _j.updateOutlineColor(this.outlineColor);
    }
    updateOpacities(opacities) {
        this.planeOpacity = opacities.plane;
    }
    hasData() {
        return this.transform != null && this.normal != null;
    }
    createOrUpdateElements() {
        if (this.transform != null && this.normal != null && this.frame != null) {
            if (this.arrow == null) {
                this.createElements(this.transform, this.normal, this.frame);
            }
            else {
                this.updateElements(this.transform, this.normal, this.frame);
            }
        }
    }
    createElements(transform, normal, frame) {
        this.reglCommand = regl({
            canvas: this.canvasElement,
            extensions: 'angle_instanced_arrays',
        });
        const { createShape } = shapeBuilder(this.reglCommand);
        const triangleSize = this.computeTriangleSize(vector3.fromMatrixPosition(transform), frame);
        this.arrow = new TriangleMesh(createShape, 'hit-normal-arrow', computeArrowNdcValues(transform, frame.scene.camera, normal, triangleSize), this.outlineColor, this.arrowFillColor);
        this.plane = new Mesh(createShape, 'hit-plane', computePlaneNdcValues(transform, frame.scene.camera, normal, triangleSize * DEFAULT_PLANE_SIZE_SCALAR), this.outlineColor, this.planeFillColor, {
            opacity: this.getPlaneOpacity(),
            depth: 0.5,
        });
        this.point = new Mesh(createShape, 'hit-position', computePointNdcValues(transform, frame.scene.camera, normal, triangleSize * DEFAULT_POINT_SIZE_SCALAR), this.outlineColor, this.outlineColor, {
            join: 'round',
            depth: 1,
        });
        this.axis = new AxisLine(createShape, 'hit-normal-axis', axisPositions(transform, frame.scene.camera, this.arrow), this.outlineColor, this.arrowFillColor);
        this.availableElements = [this.arrow, this.point, this.plane, this.axis];
    }
    updateElements(transform, normal, frame) {
        var _a;
        const triangleSize = this.computeTriangleSize(vector3.fromMatrixPosition(transform), frame);
        if (this.arrow != null) {
            this.arrow.updatePoints(computeArrowNdcValues(transform, frame.scene.camera, normal, triangleSize));
            (_a = this.axis) === null || _a === void 0 ? void 0 : _a.updatePoints(axisPositions(transform, frame.scene.camera, this.arrow));
        }
        if (this.plane != null) {
            this.plane.updatePoints(computePlaneNdcValues(transform, frame.scene.camera, normal, triangleSize * DEFAULT_PLANE_SIZE_SCALAR));
        }
        if (this.point != null) {
            this.point.updatePoints(computePointNdcValues(transform, frame.scene.camera, normal, triangleSize * DEFAULT_POINT_SIZE_SCALAR));
        }
    }
    getPlaneOpacity() {
        if (this.planeOpacity != null) {
            return typeof this.planeOpacity === 'string'
                ? parseFloat(this.planeOpacity)
                : this.planeOpacity;
        }
        return DEFAULT_PLANE_OPACITY;
    }
}

const viewerHitResultIndicatorCss = () => `:host{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;--viewer-hit-result-indicator-arrow-color:#0099cc;--viewer-hit-result-indicator-plane-color:#0099cc;--viewer-hit-result-indicator-outline-color:#000000;--viewer-hit-result-indicator-plane-opacity:0.75}.indicator{position:absolute;top:0;left:0}`;

const ViewerHitResultIndicator = class {
    constructor(hostRef) {
        registerInstance(this, hostRef);
        this.arrowColor = '#0099cc';
        this.planeColor = '#0099cc';
        this.outlineColor = '#000000';
        this.planeOpacity = DEFAULT_PLANE_OPACITY;
        this.handleViewerFrameDrawn = () => {
            this.updatePropsFromViewer();
        };
        this.handleViewerDimensionsChange = () => {
            writeDOM(() => {
                if (this.viewer != null && this.canvasRef != null) {
                    this.canvasRef.width = this.viewer.viewport.width;
                    this.canvasRef.height = this.viewer.viewport.height;
                    this.updateAndRedrawIndicator();
                }
            });
        };
        this.handleResize = () => {
            if (this.canvasRef != null) {
                this.updateAndRedrawIndicator();
            }
        };
        this.updatePropsFromViewer = () => {
            const { frame } = this.viewer || {};
            if (frame != null) {
                const widget = this.getIndicator();
                widget.updateFrame(frame);
            }
        };
        this.setupIndicator = (canvasRef) => {
            var _a, _b;
            console.debug(`Initializing hit indicator. [initial-position=${JSON.stringify(this.position)}, initial-normal=${JSON.stringify(this.normal)} has-initial-frame=${((_a = this.viewer) === null || _a === void 0 ? void 0 : _a.frame) != null}]`);
            this.indicator = new HitIndicator(canvasRef, {
                arrow: this.arrowColor,
                plane: this.planeColor,
            }, {
                plane: this.planeOpacity,
            });
            this.transform = this.createTransform();
            this.indicator.updateTransformAndNormal(this.transform, this.normal);
            if (((_b = this.viewer) === null || _b === void 0 ? void 0 : _b.frame) != null) {
                this.indicator.updateFrame(this.viewer.frame);
            }
            return this.indicator;
        };
        this.updateAndRedrawIndicator = () => {
            readDOM(() => {
                this.getIndicator().updateAndDraw();
            });
        };
        this.createTransform = () => {
            if (this.position != null) {
                return matrix4.makeTranslation(this.position);
            }
        };
        this.getIndicator = () => {
            if (this.indicator == null && this.canvasRef != null) {
                return this.setupIndicator(this.canvasRef);
            }
            else if (this.indicator != null) {
                return this.indicator;
            }
            else {
                throw new Error('Hit indicator was not initialized. The canvas element may not have been initialized.');
            }
        };
    }
    componentDidLoad() {
        this.handleViewerChanged(this.viewer, undefined);
        this.canvasResizeObserver = new ResizeObserver(this.handleResize);
        if (this.canvasRef != null) {
            this.canvasResizeObserver.observe(this.canvasRef);
            this.setupIndicator(this.canvasRef);
        }
        readDOM(() => {
            var _a, _b;
            const hostStyles = window.getComputedStyle(this.hostEl);
            this.arrowColor = parseCssColorValue(hostStyles, '--viewer-hit-result-indicator-arrow-color');
            this.planeColor = parseCssColorValue(hostStyles, '--viewer-hit-result-indicator-plane-color');
            this.outlineColor = parseCssColorValue(hostStyles, '--viewer-hit-result-indicator-outline-color');
            this.planeOpacity = hostStyles
                .getPropertyValue('--viewer-hit-result-indicator-plane-opacity')
                .trim();
            (_a = this.indicator) === null || _a === void 0 ? void 0 : _a.updateColors({
                arrow: this.arrowColor,
                plane: this.planeColor,
                outline: this.outlineColor,
            });
            (_b = this.indicator) === null || _b === void 0 ? void 0 : _b.updateOpacities({
                plane: this.planeOpacity,
            });
        });
    }
    disconnectedCallback() {
        var _a, _b;
        (_a = this.canvasResizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
        (_b = this.indicator) === null || _b === void 0 ? void 0 : _b.dispose();
    }
    /**
     * @ignore
     */
    handleViewerChanged(newViewer, oldViewer) {
        oldViewer === null || oldViewer === void 0 ? void 0 : oldViewer.removeEventListener('frameDrawn', this.handleViewerFrameDrawn);
        oldViewer === null || oldViewer === void 0 ? void 0 : oldViewer.removeEventListener('dimensionschange', this.handleViewerDimensionsChange);
        newViewer === null || newViewer === void 0 ? void 0 : newViewer.addEventListener('frameDrawn', this.handleViewerFrameDrawn);
        newViewer === null || newViewer === void 0 ? void 0 : newViewer.addEventListener('dimensionschange', this.handleViewerDimensionsChange);
    }
    /**
     * @ignore
     */
    handlePositionChanged(newPosition, oldPosition) {
        var _a;
        this.transform = this.createTransform();
        console.debug(`Updating indicator position [previous=${JSON.stringify(oldPosition)}, current=${JSON.stringify(newPosition)}]`);
        (_a = this.indicator) === null || _a === void 0 ? void 0 : _a.updateTransformAndNormal(this.transform, this.normal);
    }
    handleNormalChanged(newNormal, oldNormal) {
        var _a;
        console.debug(`Updating indicator normal [previous=${JSON.stringify(oldNormal)}, current=${JSON.stringify(newNormal)}]`);
        if (newNormal) {
            (_a = this.indicator) === null || _a === void 0 ? void 0 : _a.updateTransformAndNormal(this.transform, this.normal);
        }
    }
    render() {
        var _a, _b;
        return (h(Host, { key: 'b01a77bd8351c40aa405af4c6b78b455de415a18' }, h("canvas", { key: 'bef28c167aa8f5db50e8130111d63592ba9cd4b4', ref: (el) => {
                this.canvasRef = el;
            }, class: "indicator", width: (_a = this.viewer) === null || _a === void 0 ? void 0 : _a.viewport.width, height: (_b = this.viewer) === null || _b === void 0 ? void 0 : _b.viewport.height })));
    }
    get hostEl() { return getElement(this); }
    static get watchers() { return {
        "viewer": [{
                "handleViewerChanged": 0
            }],
        "position": [{
                "handlePositionChanged": 0
            }],
        "normal": [{
                "handleNormalChanged": 0
            }]
    }; }
};
ViewerHitResultIndicator.style = viewerHitResultIndicatorCss();

export { ViewerHitResultIndicator as vertex_viewer_hit_result_indicator };
//# sourceMappingURL=vertex-viewer-hit-result-indicator.entry.js.map

//# sourceMappingURL=vertex-viewer-hit-result-indicator.entry.js.map