entity/pointCloud/PointCloudHandler.tstypescript
import * as shaders from "../../shaders/pointCloud";
import { EntityCollection } from "../EntityCollection";
import { PointCloud } from "./PointCloud";
import { Renderer } from "../../renderer/Renderer";
import { Scene } from "../../scene/Scene";

class PointCloudHandler {
    static __counter__: number = 0;
    protected __id: number;

    /**
     * Picking rendering option.
     * @public
     * @type {boolean}
     */
    public pickingEnabled = true;

    /**
     * Parent collection
     * @public
     * @type {EntityCollection}
     */
    public _entityCollection: EntityCollection;

    /**
     * Renderer
     * @protected
     * @type {Renderer|null}
     */
    protected _renderer: Renderer | null;

    /**
     * Point cloud array
     * @protected
     * @type {Array.<PointCloud>}
     */
    protected _pointClouds: PointCloud[];

    constructor(entityCollection: EntityCollection) {
        this.__id = PointCloudHandler.__counter__++;

        this.pickingEnabled = true;
        this._entityCollection = entityCollection;
        this._renderer = null;
        this._pointClouds = [];
    }

    /**
     * Requests the next frame to be rendered.
     * @public
     */
    public requestRedraw() {
        this._renderer && (this._renderer.handler.needRedraw = true);
    }

    protected _initProgram() {
        if (this._renderer && this._renderer.handler) {
            if (!this._renderer.handler.programs.pointCloud) {
                this._renderer.handler.addProgram(shaders.pointCloud());
            }
        }
    }

    public bindScene(scene: Scene) {
        this._renderer = scene.renderer;
        this._initProgram();
        for (let i = 0; i < this._pointClouds.length; i++) {
            this._pointClouds[i].bindScene(scene);
        }
    }

    public add(pointCloud: PointCloud) {
        if (pointCloud._handlerIndex === -1) {
            pointCloud._handler = this;
            pointCloud._handlerIndex = this._pointClouds.length;
            this._pointClouds.push(pointCloud);
            this._entityCollection &&
                this._entityCollection.scene &&
                pointCloud.bindScene(this._entityCollection.scene);
        }
    }

    public remove(pointCloud: PointCloud) {
        let index = pointCloud._handlerIndex;
        if (index !== -1) {
            pointCloud._deleteBuffers();

            pointCloud._handlerIndex = -1;
            pointCloud._handler = null;
            this._pointClouds.splice(index, 1);
            this._reindexPointCloudArray(index);
        }
    }

    protected _reindexPointCloudArray(startIndex: number) {
        let pc = this._pointClouds;
        for (let i = startIndex; i < pc.length; i++) {
            pc[i]._handlerIndex = i;
        }
    }

    public draw() {
        let i = this._pointClouds.length;
        while (i--) {
            this._pointClouds[i].draw();
        }
    }

    public drawPicking() {
        if (this.pickingEnabled) {
            let i = this._pointClouds.length;
            while (i--) {
                this._pointClouds[i].drawPicking();
            }
        }
    }

    public clear() {
        let i = this._pointClouds.length;
        while (i--) {
            this._pointClouds[i]._deleteBuffers();
            this._pointClouds[i]._handler = null;
            this._pointClouds[i]._handlerIndex = -1;
        }
        this._pointClouds.length = 0;
        this._pointClouds = [];
    }
}

export { PointCloudHandler };