Make scene.freezeActiveMeshes much more usable

I am not really able to go all day right now, but have managed to implement this except adaptive. Am not too concerned if I am not posting perfect code, since in order to use as a sub-class requires the ability to have a mesh sub-class & AFAIK I am the only one doing embedded graphics.

Here is the entire scene class

module  XXX {
    export enum RenderLoopBehaviors  { cpu_favored, gpu_favored, adaptive };

    export class Scene extends BABYLON.Scene {
        constructor(engine: BABYLON.Engine, options?: BABYLON.SceneOptions) {
            super(engine, options);

            // front run _evaluateActiveMeshes
            this["_stockEvaluateActiveMeshes"] = this["_evaluateActiveMeshes"];
            this["_evaluateActiveMeshes"] = this["_PRE_EvaluateActiveMeshes"];
        }

        private _loopBehavior = RenderLoopBehaviors.cpu_favored; // default for back compatablity
        private _loopBehaviorState = this._loopBehavior; // current state, never really uses adaptive setting for long

        public get loopBehavior() { return this._loopBehavior; }
        public set loopBehavior(val : RenderLoopBehaviors) {
            this._loopBehavior = val;
            this._loopBehaviorState = this._loopBehavior;

            if (this._loopBehaviorState !== RenderLoopBehaviors.cpu_favored) {
                this.freezeActiveMeshes(false, null, null, false);
            } else {
                this.unfreezeActiveMeshes();
            }
        }
        public get loopBehaviorState() { return this._loopBehaviorState; }

        // a mesh was added / (dis)enabled / layer mask set / changed from - to visibility == 0
        public activeMeshesOutOfDate = true;
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        /**
         * @override
         * This is near identical to stock, but since it calls _evaluateActiveMeshes()
         * that line must be changed.  Also, setting alwaysSelectAsActiveMesh = true
         */
        public freezeActiveMeshes(skipEvaluateActiveMeshes = false, onSuccess?: () => void, onError?: (message: string) => void, freezeMeshes = true): Scene {
            this.executeWhenReady(() => {
                if (!this.activeCamera) {
                    onError && onError('No active camera found');
                    return;
                }

                if (!this._frustumPlanes) {
                    this.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix());
                }

                // this must occur BEFORE running eval
                for (const mesh of this.meshes) {
                    mesh.alwaysSelectAsActiveMesh = true;
                }

                this["_stockEvaluateActiveMeshes"](); // calling the stock version
                this._activeMeshesFrozen = true;
                this["skipEvaluateActiveMeshesCompletely"] = skipEvaluateActiveMeshes;

                if (freezeMeshes) {
                    const actives = <BABYLON.SmartArray<BABYLON.AbstractMesh>> this["_activeMeshes"];
                    for (var index = 0; index < actives.length; index++) {
                        actives.data[index]._freeze();
                    }
                }
                onSuccess && onSuccess();
            });
            return this;
        }
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        /**
         * @override
         * Setting alwaysSelectAsActiveMesh = false
         */
        public unfreezeActiveMeshes(): BABYLON.Scene {
            for (const mesh of this.meshes) {
                mesh.alwaysSelectAsActiveMesh = false;
            }
            return super.unfreezeActiveMeshes();
        }
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        private _PRE_EvaluateActiveMeshes() : void {
            // in gpu mode & meshes out of date
            if (this._loopBehaviorState !== RenderLoopBehaviors.cpu_favored && this.activeMeshesOutOfDate) {
                this._activeMeshesFrozen = false; // quicker than actually bothering to unfreeze
                this.freezeActiveMeshes(false, null, null, false); // already does an eval call
                this.activeMeshesOutOfDate = false;

            // in cpu mode or meshes still up to date
            } else {
                this["_stockEvaluateActiveMeshes"]();
            }
        }
    }
}

Here are the relevant adds to my mesh sub-class

constructor(name: string, scene: BABYLON.Scene, parent: BABYLON.Node = null, source?: Mesh, doNotCloneChildren?: boolean) {
    super(name, scene, parent, source, doNotCloneChildren);

    // still allow for use of the stock scene class
    if (scene instanceof XXX.Scene) {
        this.onMeshReadyObservable.add(() => { scene.activeMeshesOutOfDate = true; } );
    }
    . . .
}
// ============================ support overrides for RenderLoop =============================
/**
 * @override
 */
 public setEnabled(value : boolean) : void {
    super.setEnabled(value);
    const scene = this.getScene();
    if (scene instanceof XXX.Scene) scene.activeMeshesOutOfDate = true;
 }

/**
 * @override
 */
public set layerMask(value: number) {
    super.layerMask = value;
    const scene = this.getScene();
    if (scene instanceof XXX.Scene) scene.activeMeshesOutOfDate = true;
 }
/**
 * @override
 * If you overide a setter, you must also override the getter
 */
public get layerMask()  : number {
    return super.layerMask;
}

/**
 * @override
 */
public set visibility(value: number) {
    super.visibility = value;
    const scene = this.getScene();
    if (scene instanceof XXX.Scene) scene.activeMeshesOutOfDate = true;
}

/**
 * @override
 * If you overide a setter, you must also override the getter
 */
public get visibility() : number {
    return super.visibility;
}

/**
 * isVisible is a property, not a setter, so cannot override excactly.
 * Implementing this as a PR should change this to a getter / setter.
 */
 public setIsVisible(value : boolean) :void {
    this.isVisible = value;
    const scene = this.getScene();
    if (scene instanceof XXX.Scene) scene.activeMeshesOutOfDate = true;
 }

In coming days, I will do some more testing. Probably not implement adaptive for my own needs unless I determine I need it myself. Will put any code changes discovered in as edits.