"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Tiles
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.TileBoundingBoxes = exports.TileLoadPriority = exports.TileVisibility = exports.TileLoadStatus = exports.Tile = void 0;
exports.addRangeGraphic = addRangeGraphic;
const core_bentley_1 = require("@itwin/core-bentley");
const core_geometry_1 = require("@itwin/core-geometry");
const core_common_1 = require("@itwin/core-common");
const IModelApp_1 = require("../IModelApp");
const internal_1 = require("./internal");
// cSpell:ignore undisplayable bitfield
const scratchRange2d = [new core_geometry_1.Point2d(), new core_geometry_1.Point2d(), new core_geometry_1.Point2d(), new core_geometry_1.Point2d()];
/** @internal */
function addRangeGraphic(builder, range, is2d) {
    if (!is2d) {
        builder.addRangeBox(range);
        return;
    }
    // 3d box is useless in 2d and will be clipped by near/far planes anyway
    const pts = scratchRange2d;
    pts[0].set(range.low.x, range.low.y);
    pts[1].set(range.high.x, range.low.y);
    pts[2].set(range.high.x, range.high.y);
    pts[3].set(range.low.x, range.high.y);
    builder.addLineString2d(pts, 0);
}
const scratchWorldFrustum = new core_common_1.Frustum();
const scratchRootFrustum = new core_common_1.Frustum();
const scratchWorldSphere = new core_common_1.BoundingSphere();
const scratchPoint4d = core_geometry_1.Point4d.createZero();
const scratchFrustum = new core_common_1.Frustum();
/** A 3d tile within a [[TileTree]].
 *
 * A tile represents the contents of some sub-volume of the tile tree's volume. It may produce graphics representing those contents, or may have no graphics.
 * A tile can have child tiles that further sub-divide its own volume, providing higher-resolution representations of its contents. A tile that has no children is
 * referred to as a "leaf" of the tile tree. A non-leaf tile's children are produced when they are needed, and discarded when no longer needed.
 * A tile's contents can be discarded at any time by [[TileAdmin]] when GPU memory needs to be reclaimed; or when the Tile itself is discarded via
 * [[Tile.dispose]].
 *
 * Several public [[Tile]] methods carry a warning that they should **not** be overridden by subclasses; typically a protected method exists that can be overridden instead.
 * For example, [[loadChildren]] should not be overridden, but it calls [[_loadChildren]], which must be overridden because it is abstract.
 * @public
 * @extensions
 */
class Tile {
    _state = 0 /* TileState.NotReady */;
    _children;
    _rangeGraphic;
    _rangeGraphicType = TileBoundingBoxes.None;
    /** This tile's renderable content. */
    _graphic;
    /** True if this tile ever had graphics loaded. Used to determine when a tile's graphics were later freed to conserve memory. */
    _hadGraphics = false;
    /** Uniquely identifies this tile's content in the context of its tree. */
    _contentId;
    /** The current loading state of this tile's children. Child tiles are loaded on-demand, potentially asynchronously. */
    _childrenLoadStatus;
    /** @internal */
    _request;
    /** @internal */
    _isLeaf;
    /** A volume no larger than this tile's `range`, and optionally more tightly encompassing its contents, used for more accurate culling.
     * [[contentRange]] uses this range if defined; otherwise it uses [[range]].
     */
    _contentRange;
    /** The maximum size in pixels this tile can be drawn. If the size of the tile on screen exceeds this maximum, a higher-resolution tile should be drawn in its place. */
    _maximumSize;
    /** The [[TileTree]] to which this tile belongs. */
    tree;
    /** The volume of space occupied by this tile. Its children are guaranteed to also be contained within this volume. */
    range;
    /** The parent of this tile, or undefined if it is the [[TileTree]]'s root tile. */
    parent;
    /** The depth of this tile within its [[TileTree]]. The root tile has a depth of zero. */
    depth;
    /** The bounding sphere for this tile. */
    boundingSphere;
    /** The point at the center of this tile's volume. */
    get center() { return this.boundingSphere.center; }
    /** The radius of a sphere fully encompassing this tile's volume - used for culling. */
    get radius() { return this.boundingSphere.radius; }
    /** Tracks the usage of this tile. After a period of disuse, the tile may be [[prune]]d to free up memory. */
    usageMarker = new internal_1.TileUsageMarker();
    /** Exclusively for use by LRUTileList. @internal */
    previous;
    /** Exclusively for use by LRUTileList. @internal */
    next;
    /** Exclusively for use by LRUTileList. @internal */
    bytesUsed = 0;
    /** Exclusively for use by LRUTileList. @internal */
    tileUserIds;
    /** Constructor */
    constructor(params, tree) {
        this.tree = tree;
        this.parent = params.parent;
        this.depth = undefined !== this.parent ? this.parent.depth + 1 : 0;
        this.range = params.range;
        this._maximumSize = params.maximumSize;
        this._contentRange = params.contentRange;
        this._contentId = params.contentId;
        const center = this.range.low.interpolate(0.5, this.range.high);
        const radius = 0.5 * this.range.low.distance(this.range.high);
        this.boundingSphere = new core_common_1.BoundingSphere(center, radius);
        if (params.maximumSize <= 0)
            this.setIsReady();
        this._isLeaf = true === params.isLeaf;
        this._childrenLoadStatus = (undefined === tree.maxDepth || this.depth < tree.maxDepth) ? internal_1.TileTreeLoadStatus.NotLoaded : internal_1.TileTreeLoadStatus.Loaded;
    }
    /** Free memory-consuming resources owned by this tile to reduce memory pressure.
     * By default, this calls [[disposeContents]]. Problematic subclasses (MapTile, ImageryMapTile) may opt out for now by overriding this method to do nothing.
     * That option may be removed in the future.
     * @alpha
     */
    freeMemory() {
        this.disposeContents();
    }
    /** Dispose of resources held by this tile. */
    disposeContents() {
        this._state = 0 /* TileState.NotReady */;
        this._graphic = (0, core_bentley_1.dispose)(this._graphic);
        this._rangeGraphic = (0, core_bentley_1.dispose)(this._rangeGraphic);
        this._rangeGraphicType = TileBoundingBoxes.None;
        IModelApp_1.IModelApp.tileAdmin.onTileContentDisposed(this);
    }
    /** Dispose of resources held by this tile and all of its children, marking it and all of its children as "abandoned". */
    [Symbol.dispose]() {
        this.disposeContents();
        this._state = 5 /* TileState.Abandoned */;
        this.disposeChildren();
    }
    /** @deprecated in 5.0 - will not be removed until after 2026-06-13. Use [Symbol.dispose] instead. */
    dispose() {
        this[Symbol.dispose]();
    }
    /** This tile's child tiles, if they exist and are loaded. The children are fully contained within this tile's volume and provide higher-resolution graphics than this tile.
     * @see [[loadChildren]]
     */
    get children() { return this._children; }
    /** The [[IModelConnection]] to which this tile belongs. */
    get iModel() { return this.tree.iModel; }
    /** Uniquely identifies this tile's content. */
    get contentId() { return this._contentId; }
    /** True if this tile's content is currently being loaded. */
    get isLoading() { return TileLoadStatus.Loading === this.loadStatus; }
    /** True if a request for this tile's content has been enqueued. */
    get isQueued() { return TileLoadStatus.Queued === this.loadStatus; }
    /** True if an attempt to load this tile's content failed. */
    get isNotFound() { return TileLoadStatus.NotFound === this.loadStatus; }
    /** True if this tile's content has been loaded and is ready to be drawn. */
    get isReady() { return TileLoadStatus.Ready === this.loadStatus; }
    /** Indicates the tile should not be selected for display because it is out of the range of LODs supported by the tile provider.
     * @see [[ImageryMapTile.isOutOfLodRange]].
     * @alpha
     */
    get isOutOfLodRange() { return false; }
    /** @public */
    setNotFound() {
        this._state = 4 /* TileState.NotFound */;
    }
    /** @public */
    setIsReady() {
        if (this.hasGraphics)
            this._hadGraphics = true;
        this._state = 3 /* TileState.Ready */;
        IModelApp_1.IModelApp.tileAdmin.onTileContentLoaded(this);
    }
    /** @public */
    setLeaf() {
        // Don't potentially re-request the children later.
        this.disposeChildren();
        this._isLeaf = true;
        this._childrenLoadStatus = internal_1.TileTreeLoadStatus.Loaded;
    }
    /** True if this tile has no child tiles. */
    get isLeaf() { return this._isLeaf; }
    /** @internal */
    get isEmpty() { return this.isReady && !this.hasGraphics && this.isLeaf; }
    /** @internal */
    get isDisplayable() { return 0 < this.maximumSize; }
    /** The maximum size in pixels this tile can be drawn. If the size of the tile on screen exceeds this maximum, a higher-resolution tile should be drawn in its place. */
    get maximumSize() { return this._maximumSize; }
    /** @internal */
    get isParentDisplayable() { return undefined !== this.parent && this.parent.isDisplayable; }
    /** @internal */
    get isUndisplayableRootTile() { return undefined === this.parent && !this.isDisplayable; }
    /** @internal */
    get request() { return this._request; }
    set request(request) {
        (0, core_bentley_1.assert)(undefined === request || undefined === this.request);
        this._request = request;
    }
    /** Compute the load priority of this tile. This determines which tiles' contents are requested first.
     * @param _viewports The subset of `users` that are [[Viewport]]s - typically, these viewports want to display the tile's content.
     * @param users The [[TileUser]]s that are currently using the tile for some purpose, such as displaying its content.
     * @returns The priority.
     * @see [[TileLoadPriority]] for suggested priority values.
     */
    computeLoadPriority(_viewports, _users) {
        return this.depth;
    }
    /** True if this tile has graphics ready to draw. */
    get hasGraphics() { return undefined !== this._graphic; }
    /** True if this tile has a known volume tightly encompassing its graphics. */
    get hasContentRange() { return undefined !== this._contentRange; }
    /** A volume no larger than this tile's `range`, and optionally more tightly encompassing its contents, used for more accurate culling. */
    get contentRange() {
        if (undefined !== this._contentRange)
            return this._contentRange;
        else if (undefined === this.parent && undefined !== this.tree.contentRange)
            return this.tree.contentRange;
        else
            return this.range;
    }
    /** Tile contents are loaded asynchronously on demand. This member tracks the current loading status of this tile's contents. */
    get loadStatus() {
        switch (this._state) {
            case 0 /* TileState.NotReady */: {
                if (undefined === this.request)
                    return TileLoadStatus.NotLoaded;
                else if (internal_1.TileRequest.State.Loading === this.request.state)
                    return TileLoadStatus.Loading;
                (0, core_bentley_1.assert)(internal_1.TileRequest.State.Completed !== this.request.state && internal_1.TileRequest.State.Failed !== this.request.state); // this.request should be undefined in these cases...
                return TileLoadStatus.Queued;
            }
            case 3 /* TileState.Ready */: {
                (0, core_bentley_1.assert)(undefined === this.request);
                return TileLoadStatus.Ready;
            }
            case 4 /* TileState.NotFound */: {
                (0, core_bentley_1.assert)(undefined === this.request);
                return TileLoadStatus.NotFound;
            }
            default: {
                (0, core_bentley_1.assert)(5 /* TileState.Abandoned */ === this._state);
                return TileLoadStatus.Abandoned;
            }
        }
    }
    /** Produce the graphics that should be drawn. */
    produceGraphics() {
        return this._graphic;
    }
    setGraphic(graphic) {
        (0, core_bentley_1.dispose)(this._graphic);
        this._graphic = graphic;
        this.setIsReady();
    }
    /** Set this tile's content to the result of [[readContent]] */
    setContent(content) {
        const { graphic, isLeaf, contentRange } = content;
        this.setGraphic(graphic);
        if (undefined !== isLeaf && isLeaf !== this._isLeaf) {
            if (isLeaf)
                this.setLeaf();
            else
                this._isLeaf = false;
        }
        if (undefined !== contentRange)
            this._contentRange = contentRange;
        this.setIsReady();
    }
    /** Disclose any resources owned by this tile, other than its [[RenderGraphic]].
     * @internal
     */
    _collectStatistics(_stats) { }
    /** Disclose resources owned by this tile and (by default) all of its child tiles.
     * @note Do not override this method! Override `_collectStatistics` instead.
     * @internal
     */
    collectStatistics(stats, includeChildren = true) {
        if (undefined !== this._graphic)
            this._graphic.collectStatistics(stats);
        this._collectStatistics(stats);
        if (!includeChildren)
            return;
        const children = this.children;
        if (undefined !== children)
            for (const child of children)
                child.collectStatistics(stats);
    }
    /** If this tile's child tiles have not yet been requested, enqueue an asynchronous request to load them.
     * @note This function itself is *not* asynchronous - it immediately returns the current loading status.
     * @note Do not override this method - implement [[_loadChildren]].
     */
    loadChildren() {
        if (this._childrenLoadStatus !== internal_1.TileTreeLoadStatus.NotLoaded)
            return this._childrenLoadStatus;
        this._childrenLoadStatus = internal_1.TileTreeLoadStatus.Loading;
        this._loadChildren((children) => {
            this._children = children;
            this._childrenLoadStatus = internal_1.TileTreeLoadStatus.Loaded;
            if (undefined === children || 0 === children.length)
                this._isLeaf = true;
            IModelApp_1.IModelApp.tileAdmin.onTileChildrenLoad.raiseEvent(this);
        }, (_error) => {
            this._isLeaf = true;
            this._childrenLoadStatus = internal_1.TileTreeLoadStatus.NotFound;
            IModelApp_1.IModelApp.tileAdmin.onTileChildrenLoad.raiseEvent(this);
        });
        return this._childrenLoadStatus;
    }
    /** Dispose of this tile's child tiles and mark them as "not loaded". */
    disposeChildren() {
        const children = this.children;
        if (undefined === children)
            return;
        for (const child of children)
            child[Symbol.dispose]();
        this._childrenLoadStatus = internal_1.TileTreeLoadStatus.NotLoaded;
        this._children = undefined;
    }
    /** Returns true if this tile's bounding volume is culled by the frustum or clip volumes specified by `args`. */
    isRegionCulled(args) {
        return this.isCulled(this.range, args, true, this.boundingSphere);
    }
    /** Returns true if this tile's content bounding volume is culled by the frustum or clip volumes specified by `args`. */
    isContentCulled(args) {
        return this.isCulled(this.contentRange, args, false);
    }
    isCulled(range, args, testClipIntersection, sphere) {
        const box = core_common_1.Frustum.fromRange(range, scratchRootFrustum);
        return this.isFrustumCulled(box, args, testClipIntersection, sphere);
    }
    isFrustumCulled(box, args, testClipIntersection, sphere) {
        const worldBox = box.transformBy(args.location, scratchWorldFrustum);
        const worldSphere = sphere?.transformBy(args.location, scratchWorldSphere);
        // Test against frustum.
        if (core_common_1.FrustumPlanes.Containment.Outside === args.frustumPlanes.computeFrustumContainment(worldBox, worldSphere))
            return true;
        // Test against TileTree's own clip volume, if any.
        if (undefined !== args.clip && core_geometry_1.ClipPlaneContainment.StronglyOutside === args.clip.classifyPointContainment(worldBox.points))
            return true;
        // Test against view clip, if any (will be undefined if TileTree does not want view clip applied to it).
        if (undefined !== args.viewClip && core_geometry_1.ClipPlaneContainment.StronglyOutside === args.viewClip.classifyPointContainment(worldBox.points))
            return true;
        // Test against intersection clip - reject if tile doesn't intersect (used for section-cut graphics).
        if (testClipIntersection && undefined !== args.intersectionClip && core_geometry_1.ClipPlaneContainment.Ambiguous !== args.intersectionClip.classifyPointContainment(worldBox.points))
            return true;
        return false;
    }
    /** Determine the visibility of this tile according to the specified args. */
    computeVisibility(args) {
        if (this.isEmpty)
            return TileVisibility.OutsideFrustum;
        if (args.boundingRange && !args.boundingRange.intersectsRange(this.range))
            return TileVisibility.OutsideFrustum;
        // NB: We test for region culling before isDisplayable - otherwise we will never unload children of undisplayed tiles when
        // they are outside frustum
        if (this.isRegionCulled(args))
            return TileVisibility.OutsideFrustum;
        // some nodes are merely for structure and don't have any geometry
        if (!this.isDisplayable)
            return TileVisibility.TooCoarse;
        if (this.isLeaf) {
            if (this.hasContentRange && this.isContentCulled(args))
                return TileVisibility.OutsideFrustum;
            else
                return TileVisibility.Visible;
        }
        return this.meetsScreenSpaceError(args) ? TileVisibility.Visible : TileVisibility.TooCoarse;
    }
    /** Returns true if this tile is of at least high enough resolution to be displayed, per the supplied [[TileDrawArgs]]; or false if
     * a higher-resolution tile should be substituted for it.
     * This method is called by [[computeVisibility]] if the tile has passed all culling checks.
     */
    meetsScreenSpaceError(args) {
        const pixelSize = args.getPixelSize(this) * args.pixelSizeScaleFactor;
        const maxSize = this.maximumSize * args.tileSizeModifier;
        return pixelSize <= maxSize;
    }
    /** @internal */
    extendRangeForContent(range, matrix, treeTransform, frustumPlanes) {
        if (this.isEmpty || this.contentRange.isNull)
            return;
        const box = core_common_1.Frustum.fromRange(this.contentRange, scratchFrustum);
        box.transformBy(treeTransform, box);
        if (frustumPlanes !== undefined && core_common_1.FrustumPlanes.Containment.Outside === frustumPlanes.computeFrustumContainment(box))
            return;
        if (this.children === undefined) {
            for (const boxPoint of box.points) {
                const pt = matrix.multiplyPoint3d(boxPoint, 1, scratchPoint4d);
                if (pt.w > .0001)
                    range.extendXYZW(pt.x, pt.y, pt.z, pt.w);
                else
                    range.high.z = Math.max(1.0, range.high.z); // behind eye plane...
            }
        }
        else {
            for (const child of this.children)
                child.extendRangeForContent(range, matrix, treeTransform, frustumPlanes);
        }
    }
    /** Primarily for debugging purposes, compute the number of tiles below this one in the [[TileTree]]. */
    countDescendants() {
        const children = this.children;
        if (undefined === children || 0 === children.length)
            return 0;
        let count = 0;
        for (const child of children)
            count += child.countDescendants();
        return count;
    }
    /** Output this tile's graphics. */
    drawGraphics(args) {
        const gfx = this.produceGraphics();
        if (undefined === gfx)
            return;
        args.graphics.add(gfx);
        const rangeGfx = this.getRangeGraphic(args.context);
        if (undefined !== rangeGfx)
            args.graphics.add(rangeGfx);
    }
    /** @internal */
    get rangeGraphicColor() {
        return this.isLeaf ? core_common_1.ColorDef.blue : core_common_1.ColorDef.green;
    }
    /** @internal */
    getRangeGraphic(context) {
        const type = context.viewport.debugBoundingBoxes;
        if (type === this._rangeGraphicType)
            return this._rangeGraphic;
        this._rangeGraphic = (0, core_bentley_1.dispose)(this._rangeGraphic);
        this._rangeGraphicType = type;
        if (TileBoundingBoxes.None !== type) {
            const builder = context.createSceneGraphicBuilder();
            this.addRangeGraphic(builder, type);
            this._rangeGraphic = builder.finish();
        }
        return this._rangeGraphic;
    }
    /** @internal */
    addRangeGraphic(builder, type) {
        if (TileBoundingBoxes.Both === type) {
            builder.setSymbology(core_common_1.ColorDef.blue, core_common_1.ColorDef.blue, 1);
            addRangeGraphic(builder, this.range, this.tree.is2d);
            if (this.hasContentRange) {
                builder.setSymbology(core_common_1.ColorDef.red, core_common_1.ColorDef.red, 1);
                addRangeGraphic(builder, this.contentRange, this.tree.is2d);
            }
        }
        else if (TileBoundingBoxes.Sphere === type) {
            builder.setSymbology(core_common_1.ColorDef.green, core_common_1.ColorDef.green, 1);
            const x = new core_geometry_1.Vector3d(this.radius, 0, 0);
            const y = new core_geometry_1.Vector3d(0, this.radius, 0);
            const z = new core_geometry_1.Vector3d(0, 0, this.radius);
            builder.addArc(core_geometry_1.Arc3d.create(this.center, x, y), false, false);
            builder.addArc(core_geometry_1.Arc3d.create(this.center, x, z), false, false);
            builder.addArc(core_geometry_1.Arc3d.create(this.center, y, z), false, false);
        }
        else if (TileBoundingBoxes.SolidBox === type) {
            const range = this.range;
            let color = this.rangeGraphicColor;
            builder.setSymbology(color, color, 1);
            addRangeGraphic(builder, range, this.tree.is2d);
            color = color.withTransparency(0xcf);
            builder.setSymbology(color, color, 1);
            builder.addRangeBox(range, true);
        }
        else {
            const color = this.rangeGraphicColor;
            builder.setSymbology(color, color, 1);
            const range = TileBoundingBoxes.Content === type ? this.contentRange : this.range;
            addRangeGraphic(builder, range, this.tree.is2d);
        }
    }
    /** Optional corners used to compute the screen size of the tile. These are used, e.g., by reality tiles with oriented bounding boxes to
     * produce more accurate size calculation.
     */
    getSizeProjectionCorners() { return undefined; }
    /** @internal */
    clearLayers() {
        this.disposeContents();
        if (this.children)
            for (const child of this.children)
                (child).clearLayers();
    }
}
exports.Tile = Tile;
/** Describes the current status of a [[Tile]]'s content. Tile content is loaded via an asynchronous [[TileRequest]].
 * @see [[Tile.loadStatus]].
 * @public
 * @extensions
 */
var TileLoadStatus;
(function (TileLoadStatus) {
    /** No attempt to load the tile's content has been made, or the tile has since been unloaded. It currently has no graphics. */
    TileLoadStatus[TileLoadStatus["NotLoaded"] = 0] = "NotLoaded";
    /** A request has been dispatched to load the tile's contents, and a response is pending. */
    TileLoadStatus[TileLoadStatus["Queued"] = 1] = "Queued";
    /** A response has been received and the tile's graphics and other data are being loaded on the frontend. */
    TileLoadStatus[TileLoadStatus["Loading"] = 2] = "Loading";
    /** The tile has been loaded, and if the tile is displayable it has graphics. */
    TileLoadStatus[TileLoadStatus["Ready"] = 3] = "Ready";
    /** A request to load the tile's contents failed. */
    TileLoadStatus[TileLoadStatus["NotFound"] = 4] = "NotFound";
    /** The tile has been disposed. */
    TileLoadStatus[TileLoadStatus["Abandoned"] = 5] = "Abandoned";
})(TileLoadStatus || (exports.TileLoadStatus = TileLoadStatus = {}));
/**
 * Describes the visibility of a tile based on its size and a view frustum.
 * @public
 * @extensions
 */
var TileVisibility;
(function (TileVisibility) {
    /** The tile is entirely outside of the viewing frustum. */
    TileVisibility[TileVisibility["OutsideFrustum"] = 0] = "OutsideFrustum";
    /** The tile's graphics are of too low a resolution for the viewing frustum. */
    TileVisibility[TileVisibility["TooCoarse"] = 1] = "TooCoarse";
    /** The tile's graphics are of appropriate resolution for the viewing frustum. */
    TileVisibility[TileVisibility["Visible"] = 2] = "Visible";
})(TileVisibility || (exports.TileVisibility = TileVisibility = {}));
/**
 * Loosely describes the "importance" of a [[Tile]]. Requests for tiles of greater "importance" are prioritized for loading.
 * @note A lower priority value indicates higher importance.
 * @public
 * @extensions
 */
var TileLoadPriority;
(function (TileLoadPriority) {
    /** Contents of geometric models that are being interactively edited. */
    TileLoadPriority[TileLoadPriority["Dynamic"] = 5] = "Dynamic";
    /** Background map tiles. */
    TileLoadPriority[TileLoadPriority["Map"] = 15] = "Map";
    /** Typically, tiles generated from the contents of geometric models. */
    TileLoadPriority[TileLoadPriority["Primary"] = 20] = "Primary";
    /** 3d terrain tiles onto which background map imagery is draped. */
    TileLoadPriority[TileLoadPriority["Terrain"] = 10] = "Terrain";
    /** Typically, reality models. */
    TileLoadPriority[TileLoadPriority["Context"] = 40] = "Context";
    /** Supplementary tiles used to classify the contents of geometric or reality models. */
    TileLoadPriority[TileLoadPriority["Classifier"] = 50] = "Classifier";
})(TileLoadPriority || (exports.TileLoadPriority = TileLoadPriority = {}));
/**
 * Options for displaying tile bounding boxes for debugging purposes.
 *
 * Bounding boxes are color-coded based on refinement strategy:
 *  - Blue: A leaf tile (has no child tiles).
 *  - Green: An ordinary tile (sub-divides into 4 or 8 child tiles).
 *  - Red: A tile which refines to a single higher-resolution child occupying the same volume.
 * @see [[Viewport.debugBoundingBoxes]]
 * @public
 * @extensions
 */
var TileBoundingBoxes;
(function (TileBoundingBoxes) {
    /** Display no bounding boxes */
    TileBoundingBoxes[TileBoundingBoxes["None"] = 0] = "None";
    /** Display boxes representing the tile's full volume. */
    TileBoundingBoxes[TileBoundingBoxes["Volume"] = 1] = "Volume";
    /** Display boxes representing the range of the tile's contents, which may be tighter than (but never larger than) the tile's full volume. */
    TileBoundingBoxes[TileBoundingBoxes["Content"] = 2] = "Content";
    /** Display both volume and content boxes. */
    TileBoundingBoxes[TileBoundingBoxes["Both"] = 3] = "Both";
    /** Display boxes for direct children, where blue boxes indicate empty volumes. */
    TileBoundingBoxes[TileBoundingBoxes["ChildVolumes"] = 4] = "ChildVolumes";
    /** Display bounding sphere. */
    TileBoundingBoxes[TileBoundingBoxes["Sphere"] = 5] = "Sphere";
    /** Display a transparent solid box representing the tile's full volume.
     * @alpha To be replaced with a separate option that applies to any of the other TileBoundingBoxes modes.
     */
    TileBoundingBoxes[TileBoundingBoxes["SolidBox"] = 6] = "SolidBox";
})(TileBoundingBoxes || (exports.TileBoundingBoxes = TileBoundingBoxes = {}));
//# sourceMappingURL=Tile.js.map