Browse Source

Merge pull request #5786 from BabylonJS/ray-disconnect

9k less :)
sebavan 6 years ago
parent
commit
94ca2b6a6d

+ 2 - 1
src/Audio/sound.ts

@@ -7,6 +7,7 @@ import { Engine } from "../Engines/engine";
 import { AbstractMesh } from "../Meshes/abstractMesh";
 import { TransformNode } from "../Meshes/transformNode";
 import { Logger } from "../Misc/logger";
+import { _DevTools } from '../Misc/devTools';
 
 /**
  * Defines a sound that can be played in the application.
@@ -115,7 +116,7 @@ export class Sound {
 
     /** @hidden */
     public static _SceneComponentInitialization: (scene: Scene) => void = (_) => {
-        throw "Import AudioSceneComponent before creating sound.";
+        throw _DevTools.WarnImport("AudioSceneComponent");
     }
 
     /**

+ 4 - 15
src/Cameras/camera.ts

@@ -9,15 +9,16 @@ import { Matrix, Vector3, Viewport, Plane, Frustum } from "../Maths/math";
 import { Node } from "../node";
 import { Mesh } from "../Meshes/mesh";
 import { AbstractMesh } from "../Meshes/abstractMesh";
-import { Ray } from "../Culling/ray";
 import { ICullable } from "../Culling/boundingInfo";
 import { Logger } from "../Misc/logger";
 import { _TypeStore } from '../Misc/typeStore';
+import { _DevTools } from '../Misc/devTools';
 
 declare type PostProcess = import("../PostProcesses/postProcess").PostProcess;
 declare type RenderTargetTexture = import("../Materials/Textures/renderTargetTexture").RenderTargetTexture;
 declare type FreeCamera = import("./freeCamera").FreeCamera;
 declare type TargetCamera = import("./targetCamera").TargetCamera;
+declare type Ray = import("../Culling/ray").Ray;
 
 /**
  * This is the base class of all the camera used in the application.
@@ -26,7 +27,7 @@ declare type TargetCamera = import("./targetCamera").TargetCamera;
 export class Camera extends Node {
     /** @hidden */
     public static _createDefaultParsedCamera = (name: string, scene: Scene): Camera => {
-        throw "UniversalCamera needs to be imported before deserialization can create a default camera.";
+        throw _DevTools.WarnImport("UniversalCamera");
     }
 
     /**
@@ -811,19 +812,7 @@ export class Camera extends Node {
      * @returns the forward ray
      */
     public getForwardRay(length = 100, transform?: Matrix, origin?: Vector3): Ray {
-        if (!transform) {
-            transform = this.getWorldMatrix();
-        }
-
-        if (!origin) {
-            origin = this.position;
-        }
-        var forward = this._scene.useRightHandedSystem ? new Vector3(0, 0, -1) : new Vector3(0, 0, 1);
-        var forwardWorld = Vector3.TransformNormal(forward, transform);
-
-        var direction = Vector3.Normalize(forwardWorld);
-
-        return new Ray(origin, direction, length);
+        throw _DevTools.WarnImport("Ray");
     }
 
     /**

+ 2 - 1
src/Collisions/pickingInfo.ts

@@ -2,9 +2,10 @@ import { Nullable, FloatArray } from "../types";
 import { Vector3, Vector2, Tmp } from "../Maths/math";
 import { AbstractMesh } from "../Meshes/abstractMesh";
 import { VertexBuffer } from "../Meshes/buffer";
-import { Ray } from "../Culling/ray";
 import { Sprite } from "../Sprites/sprite";
 
+declare type Ray = import("../Culling/ray").Ray;
+
 /**
      * Information about the result of picking within a scene
      * @see https://doc.babylonjs.com/babylon101/picking_collisions

+ 233 - 0
src/Culling/ray.ts

@@ -6,6 +6,8 @@ import { PickingInfo } from "../Collisions/pickingInfo";
 import { IntersectionInfo } from "../Collisions/intersectionInfo";
 import { BoundingBox } from "./boundingBox";
 import { BoundingSphere } from "./boundingSphere";
+import { Scene } from '../scene';
+import { Camera } from '../Cameras/camera';
 /**
  * Class representing a ray with position and direction
  */
@@ -530,3 +532,234 @@ export class Ray {
         this.direction.normalize();
     }
 }
+
+// Picking
+
+declare module "../scene" {
+    export interface Scene {
+        /** @hidden */
+        _tempPickingRay: Nullable<Ray>;
+
+        /** @hidden */
+        _cachedRayForTransform: Ray;
+
+        /** @hidden */
+        _pickWithRayInverseMatrix: Matrix;
+
+        /** @hidden */
+        _internalPick(rayFunction: (world: Matrix) => Ray, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean): Nullable<PickingInfo>;
+
+        /** @hidden */
+        _internalMultiPick(rayFunction: (world: Matrix) => Ray, predicate?: (mesh: AbstractMesh) => boolean): Nullable<PickingInfo[]>;
+
+    }
+}
+
+Scene.prototype.createPickingRay = function(x: number, y: number, world: Matrix, camera: Nullable<Camera>, cameraViewSpace = false): Ray {
+    let result = Ray.Zero();
+
+    this.createPickingRayToRef(x, y, world, result, camera, cameraViewSpace);
+
+    return result;
+};
+
+Scene.prototype.createPickingRayToRef = function(x: number, y: number, world: Matrix, result: Ray, camera: Nullable<Camera>, cameraViewSpace = false): Scene {
+    var engine = this.getEngine();
+
+    if (!camera) {
+        if (!this.activeCamera) {
+            throw new Error("Active camera not set");
+        }
+
+        camera = this.activeCamera;
+    }
+
+    var cameraViewport = camera.viewport;
+    var viewport = cameraViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
+
+    // Moving coordinates to local viewport world
+    x = x / engine.getHardwareScalingLevel() - viewport.x;
+    y = y / engine.getHardwareScalingLevel() - (engine.getRenderHeight() - viewport.y - viewport.height);
+
+    result.update(x, y, viewport.width, viewport.height, world ? world : Matrix.IdentityReadOnly, cameraViewSpace ? Matrix.IdentityReadOnly : camera.getViewMatrix(), camera.getProjectionMatrix());
+    return this;
+};
+
+Scene.prototype.createPickingRayInCameraSpace = function(x: number, y: number, camera?: Camera): Ray {
+    let result = Ray.Zero();
+
+    this.createPickingRayInCameraSpaceToRef(x, y, result, camera);
+
+    return result;
+};
+
+Scene.prototype.createPickingRayInCameraSpaceToRef = function(x: number, y: number, result: Ray, camera?: Camera): Scene {
+    if (!PickingInfo) {
+        return this;
+    }
+
+    var engine = this.getEngine();
+
+    if (!camera) {
+        if (!this.activeCamera) {
+            throw new Error("Active camera not set");
+        }
+
+        camera = this.activeCamera;
+    }
+
+    var cameraViewport = camera.viewport;
+    var viewport = cameraViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
+    var identity = Matrix.Identity();
+
+    // Moving coordinates to local viewport world
+    x = x / engine.getHardwareScalingLevel() - viewport.x;
+    y = y / engine.getHardwareScalingLevel() - (engine.getRenderHeight() - viewport.y - viewport.height);
+    result.update(x, y, viewport.width, viewport.height, identity, identity, camera.getProjectionMatrix());
+    return this;
+};
+
+Scene.prototype._internalPick = function(rayFunction: (world: Matrix) => Ray, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean): Nullable<PickingInfo> {
+    if (!PickingInfo) {
+        return null;
+    }
+
+    var pickingInfo = null;
+
+    for (var meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
+        var mesh = this.meshes[meshIndex];
+
+        if (predicate) {
+            if (!predicate(mesh)) {
+                continue;
+            }
+        } else if (!mesh.isEnabled() || !mesh.isVisible || !mesh.isPickable) {
+            continue;
+        }
+
+        var world = mesh.getWorldMatrix();
+        var ray = rayFunction(world);
+
+        var result = mesh.intersects(ray, fastCheck);
+        if (!result || !result.hit) {
+            continue;
+        }
+
+        if (!fastCheck && pickingInfo != null && result.distance >= pickingInfo.distance) {
+            continue;
+        }
+
+        pickingInfo = result;
+
+        if (fastCheck) {
+            break;
+        }
+    }
+
+    return pickingInfo || new PickingInfo();
+};
+
+Scene.prototype._internalMultiPick = function(rayFunction: (world: Matrix) => Ray, predicate?: (mesh: AbstractMesh) => boolean): Nullable<PickingInfo[]> {
+    if (!PickingInfo) {
+        return null;
+    }
+    var pickingInfos = new Array<PickingInfo>();
+
+    for (var meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
+        var mesh = this.meshes[meshIndex];
+
+        if (predicate) {
+            if (!predicate(mesh)) {
+                continue;
+            }
+        } else if (!mesh.isEnabled() || !mesh.isVisible || !mesh.isPickable) {
+            continue;
+        }
+
+        var world = mesh.getWorldMatrix();
+        var ray = rayFunction(world);
+
+        var result = mesh.intersects(ray, false);
+        if (!result || !result.hit) {
+            continue;
+        }
+
+        pickingInfos.push(result);
+    }
+
+    return pickingInfos;
+};
+
+Scene.prototype.pick = function(x: number, y: number, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean, camera?: Nullable<Camera>): Nullable<PickingInfo> {
+    if (!PickingInfo) {
+        return null;
+    }
+    var result = this._internalPick((world) => {
+        if (!this._tempPickingRay) {
+            this._tempPickingRay = Ray.Zero();
+        }
+
+        this.createPickingRayToRef(x, y, world, this._tempPickingRay, camera || null);
+        return this._tempPickingRay;
+    }, predicate, fastCheck);
+    if (result) {
+        result.ray = this.createPickingRay(x, y, Matrix.Identity(), camera || null);
+    }
+    return result;
+};
+
+Scene.prototype.pickWithRay = function(ray: Ray, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean): Nullable<PickingInfo> {
+    var result = this._internalPick((world) => {
+        if (!this._pickWithRayInverseMatrix) {
+            this._pickWithRayInverseMatrix = Matrix.Identity();
+        }
+        world.invertToRef(this._pickWithRayInverseMatrix);
+
+        if (!this._cachedRayForTransform) {
+            this._cachedRayForTransform = Ray.Zero();
+        }
+
+        Ray.TransformToRef(ray, this._pickWithRayInverseMatrix, this._cachedRayForTransform);
+        return this._cachedRayForTransform;
+    }, predicate, fastCheck);
+    if (result) {
+        result.ray = ray;
+    }
+    return result;
+};
+
+Scene.prototype.multiPick = function(x: number, y: number, predicate?: (mesh: AbstractMesh) => boolean, camera?: Camera): Nullable<PickingInfo[]> {
+    return this._internalMultiPick((world) => this.createPickingRay(x, y, world, camera || null), predicate);
+};
+
+Scene.prototype.multiPickWithRay = function(ray: Ray, predicate: (mesh: AbstractMesh) => boolean): Nullable<PickingInfo[]> {
+    return this._internalMultiPick((world) => {
+        if (!this._pickWithRayInverseMatrix) {
+            this._pickWithRayInverseMatrix = Matrix.Identity();
+        }
+        world.invertToRef(this._pickWithRayInverseMatrix);
+
+        if (!this._cachedRayForTransform) {
+            this._cachedRayForTransform = Ray.Zero();
+        }
+
+        Ray.TransformToRef(ray, this._pickWithRayInverseMatrix, this._cachedRayForTransform);
+        return this._cachedRayForTransform;
+    }, predicate);
+};
+
+Camera.prototype.getForwardRay = function(length = 100, transform?: Matrix, origin?: Vector3): Ray {
+    if (!transform) {
+        transform = this.getWorldMatrix();
+    }
+
+    if (!origin) {
+        origin = this.position;
+    }
+    var forward = this._scene.useRightHandedSystem ? new Vector3(0, 0, -1) : new Vector3(0, 0, 1);
+    var forwardWorld = Vector3.TransformNormal(forward, transform);
+
+    var direction = Vector3.Normalize(forwardWorld);
+
+    return new Ray(origin, direction, length);
+};

+ 2 - 1
src/Engines/engine.ts

@@ -28,6 +28,7 @@ import { DomManagement } from "../Misc/domManagement";
 import { Logger } from "../Misc/logger";
 import { EngineStore } from "./engineStore";
 import { RenderTargetCreationOptions } from "../Materials/Textures/renderTargetCreationOptions";
+import { _DevTools } from '../Misc/devTools';
 
 declare type PostProcess = import("../PostProcesses/postProcess").PostProcess;
 declare type Texture = import("../Materials/Textures/texture").Texture;
@@ -530,7 +531,7 @@ export class Engine {
      * @returns The loading screen
      */
     public static DefaultLoadingScreenFactory(canvas: HTMLCanvasElement): ILoadingScreen {
-        throw "Import LoadingScreen or set DefaultLoadingScreenFactory on engine before using the loading screen";
+        throw _DevTools.WarnImport("LoadingScreen");
     }
 
     /**

+ 3 - 1
src/Events/pointerEvents.ts

@@ -1,9 +1,11 @@
 import { Nullable } from "../types";
 import { Vector2 } from "../Maths/math";
 import { PickingInfo } from "../Collisions/pickingInfo";
-import { Ray } from "../Culling/ray";
 import { _TimeToken } from "../Instrumentation/timeToken";
 import { _DepthCullingState, _StencilState, _AlphaState } from "../States/index";
+
+declare type Ray = import("../Culling/ray").Ray;
+
 /**
  * Gather the list of pointer event types as constants.
  */

+ 2 - 1
src/Layers/effectLayer.ts

@@ -25,6 +25,7 @@ import { Constants } from "../Engines/constants";
 
 import "../Shaders/glowMapGeneration.fragment";
 import "../Shaders/glowMapGeneration.vertex";
+import { _DevTools } from '../Misc/devTools';
 
 /**
  * Effect layer options. This helps customizing the behaviour
@@ -146,7 +147,7 @@ export abstract class EffectLayer {
 
     /** @hidden */
     public static _SceneComponentInitialization: (scene: Scene) => void = (_) => {
-        throw "Import EffectLayerSceneComponent before creating EffectLayer.";
+        throw _DevTools.WarnImport("EffectLayerSceneComponent");
     }
 
     /**

+ 2 - 1
src/LensFlares/lensFlareSystem.ts

@@ -16,6 +16,7 @@ import { Constants } from "../Engines/constants";
 
 import "../Shaders/lensFlare.fragment";
 import "../Shaders/lensFlare.vertex";
+import { _DevTools } from '../Misc/devTools';
 
 /**
  * This represents a Lens Flare System or the shiny effect created by the light reflection on the  camera lenses.
@@ -65,7 +66,7 @@ export class LensFlareSystem {
 
     /** @hidden */
     public static _SceneComponentInitialization: (scene: Scene) => void = (_) => {
-        throw "Import LensFlareSystemSceneComponent before creating LensFlareSystem.";
+        throw _DevTools.WarnImport("LensFlareSystemSceneComponent");
     }
 
     /**

+ 2 - 1
src/Lights/Shadows/shadowGenerator.ts

@@ -27,6 +27,7 @@ import "../../Shaders/shadowMap.fragment";
 import "../../Shaders/shadowMap.vertex";
 import "../../Shaders/depthBoxBlur.fragment";
 import { Observable } from '../../Misc/observable';
+import { _DevTools } from '../../Misc/devTools';
 
 /**
  * Defines the options associated with the creation of a custom shader for a shadow generator.
@@ -709,7 +710,7 @@ export class ShadowGenerator implements IShadowGenerator {
 
     /** @hidden */
     public static _SceneComponentInitialization: (scene: Scene) => void = (_) => {
-        throw "Import ShadowGeneratorSceneComponent before creating ShadowGenerator.";
+        throw _DevTools.WarnImport("ShadowGeneratorSceneComponent");
     }
 
     /**

+ 2 - 1
src/Materials/Textures/internalTexture.ts

@@ -6,6 +6,7 @@ import { IInternalTextureTracker } from "../../Materials/Textures/internalTextur
 import { _TimeToken } from "../../Instrumentation/timeToken";
 import { _DepthCullingState, _StencilState, _AlphaState } from "../../States/index";
 import { Constants } from "../../Engines/constants";
+import { _DevTools } from '../../Misc/devTools';
 
 declare type Engine = import("../../Engines/engine").Engine;
 declare type BaseTexture = import("../../Materials/Textures/baseTexture").BaseTexture;
@@ -18,7 +19,7 @@ export class InternalTexture implements IInternalTextureTracker {
 
     /** hidden */
     public static _UpdateRGBDAsync = (internalTexture: InternalTexture, data: ArrayBufferView[][], sphericalPolynomial: Nullable<SphericalPolynomial>, lodScale: number, lodOffset: number): Promise<void> => {
-        throw "environmentTextureTools needs to be imported before rebuilding RGBD textures.";
+        throw _DevTools.WarnImport("environmentTextureTools");
     }
 
     /**

+ 4 - 3
src/Materials/Textures/texture.ts

@@ -8,6 +8,7 @@ import { BaseTexture } from "../../Materials/Textures/baseTexture";
 import { Constants } from "../../Engines/constants";
 import { _AlphaState } from "../../States/index";
 import { _TypeStore } from '../../Misc/typeStore';
+import { _DevTools } from '../../Misc/devTools';
 
 declare type CubeTexture = import("../../Materials/Textures/cubeTexture").CubeTexture;
 declare type MirrorTexture = import("../../Materials/Textures/mirrorTexture").MirrorTexture;
@@ -20,15 +21,15 @@ declare type RenderTargetTexture = import("../../Materials/Textures/renderTarget
 export class Texture extends BaseTexture {
     /** @hidden */
     public static _CubeTextureParser = (jsonTexture: any, scene: Scene, rootUrl: string): CubeTexture => {
-        throw "CubeTexture needs to be imported before being deserialized.";
+        throw _DevTools.WarnImport("CubeTexture");
     }
     /** @hidden */
     public static _CreateMirror = (name: string, renderTargetSize: number, scene: Scene, generateMipMaps: boolean): MirrorTexture => {
-        throw "MirrorTexture needs to be imported before being deserialized.";
+        throw _DevTools.WarnImport("MirrorTexture");
     }
     /** @hidden */
     public static _CreateRenderTargetTexture = (name: string, renderTargetSize: number, scene: Scene, generateMipMaps: boolean): RenderTargetTexture => {
-        throw "RenderTargetTexture needs to be imported before being deserialized.";
+        throw _DevTools.WarnImport("RenderTargetTexture");
     }
 
     /** nearest is mag = nearest and min = nearest and mip = linear */

+ 1 - 1
src/Meshes/abstractMesh.ts

@@ -12,7 +12,6 @@ import { TransformNode } from "../Meshes/transformNode";
 import { SubMesh } from "../Meshes/subMesh";
 import { PickingInfo } from "../Collisions/pickingInfo";
 import { IntersectionInfo } from "../Collisions/intersectionInfo";
-import { Ray } from "../Culling/ray";
 import { ICullable, BoundingInfo } from "../Culling/boundingInfo";
 import { Material } from "../Materials/material";
 import { MaterialDefines } from "../Materials/materialDefines";
@@ -23,6 +22,7 @@ import { SolidParticle } from "../Particles/solidParticle";
 import { Constants } from "../Engines/constants";
 import { AbstractActionManager } from '../Actions/abstractActionManager';
 
+declare type Ray = import("../Culling/ray").Ray;
 declare type Collider = import("../Collisions/collider").Collider;
 
 /** @hidden */

+ 26 - 25
src/Meshes/mesh.ts

@@ -25,6 +25,7 @@ import { Constants } from "../Engines/constants";
 import { SerializationHelper } from "../Misc/decorators";
 import { Logger } from "../Misc/logger";
 import { _TypeStore } from '../Misc/typeStore';
+import { _DevTools } from '../Misc/devTools';
 
 declare type LinesMesh = import("./linesMesh").LinesMesh;
 declare type InstancedMesh = import("./instancedMesh").InstancedMesh;
@@ -2404,12 +2405,12 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
     // Instances
     /** @hidden */
     public static _instancedMeshFactory(name: string, mesh: Mesh): InstancedMesh {
-        throw "Import InstancedMesh before creating instances.";
+        throw _DevTools.WarnImport("InstancedMesh");
     }
 
     /** @hidden */
     public static _PhysicsImpostorParser(scene: Scene, physicObject: IPhysicsEnabledObject, jsonObject: any): PhysicsImpostor {
-        throw "Import PhysicsImpostor before parsing physics objects.";
+        throw _DevTools.WarnImport("PhysicsImpostor");
     }
 
     /**
@@ -2699,7 +2700,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
     // Statics
     /** @hidden */
     public static _GroundMeshParser = (parsedMesh: any, scene: Scene): Mesh => {
-        throw "Import GroundMesh before trying to parse it.";
+        throw _DevTools.WarnImport("GroundMesh");
     }
 
     /**
@@ -3003,7 +3004,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreateRibbon(name: string, pathArray: Vector3[][], closeArray: boolean, closePath: boolean, offset: number, scene?: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3017,7 +3018,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
       * @returns a new Mesh
       */
     public static CreateDisc(name: string, radius: number, tessellation: number, scene: Nullable<Scene> = null, updatable?: boolean, sideOrientation?: number): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3030,7 +3031,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreateBox(name: string, size: number, scene: Nullable<Scene> = null, updatable?: boolean, sideOrientation?: number): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3044,7 +3045,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
       * @returns a new Mesh
       */
     public static CreateSphere(name: string, segments: number, diameter: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3061,7 +3062,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreateCylinder(name: string, height: number, diameterTop: number, diameterBottom: number, tessellation: number, subdivisions: any, scene?: Scene, updatable?: any, sideOrientation?: number): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     // Torus  (Code from SharpDX.org)
@@ -3077,7 +3078,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreateTorus(name: string, diameter: number, thickness: number, tessellation: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3095,7 +3096,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreateTorusKnot(name: string, radius: number, tube: number, radialSegments: number, tubularSegments: number, p: number, q: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3108,7 +3109,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreateLines(name: string, points: Vector3[], scene: Nullable<Scene> = null, updatable: boolean = false, instance: Nullable<LinesMesh> = null): LinesMesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3124,7 +3125,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreateDashedLines(name: string, points: Vector3[], dashSize: number, gapSize: number, dashNb: number, scene: Nullable<Scene> = null, updatable?: boolean, instance?: LinesMesh): LinesMesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3145,7 +3146,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreatePolygon(name: string, shape: Vector3[], scene: Scene, holes?: Vector3[][], updatable?: boolean, sideOrientation?: number, earcutInjection = earcut): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3162,7 +3163,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static ExtrudePolygon(name: string, shape: Vector3[], depth: number, scene: Scene, holes?: Vector3[][], updatable?: boolean, sideOrientation?: number, earcutInjection = earcut): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3183,7 +3184,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static ExtrudeShape(name: string, shape: Vector3[], path: Vector3[], scale: number, rotation: number, cap: number, scene: Nullable<Scene> = null, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3207,7 +3208,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static ExtrudeShapeCustom(name: string, shape: Vector3[], path: Vector3[], scaleFunction: Function, rotationFunction: Function, ribbonCloseArray: boolean, ribbonClosePath: boolean, cap: number, scene: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3224,7 +3225,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreateLathe(name: string, shape: Vector3[], radius: number, tessellation: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3237,7 +3238,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreatePlane(name: string, size: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3252,7 +3253,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreateGround(name: string, width: number, height: number, subdivisions: number, scene?: Scene, updatable?: boolean): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3270,7 +3271,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreateTiledGround(name: string, xmin: number, zmin: number, xmax: number, zmax: number, subdivisions: { w: number; h: number; }, precision: { w: number; h: number; }, scene: Scene, updatable?: boolean): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3291,7 +3292,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreateGroundFromHeightMap(name: string, url: string, width: number, height: number, subdivisions: number, minHeight: number, maxHeight: number, scene: Scene, updatable?: boolean, onReady?: (mesh: GroundMesh) => void, alphaFilter?: number): GroundMesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3313,7 +3314,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreateTube(name: string, path: Vector3[], radius: number, tessellation: number, radiusFunction: { (i: number, distance: number): number; }, cap: number, scene: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3336,7 +3337,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
       * @returns a new Mesh
       */
     public static CreatePolyhedron(name: string, options: { type?: number, size?: number, sizeX?: number, sizeY?: number, sizeZ?: number, custom?: any, faceUV?: Vector4[], faceColors?: Color4[], updatable?: boolean, sideOrientation?: number }, scene: Scene): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3355,7 +3356,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @see http://doc.babylonjs.com/how_to/polyhedra_shapes#icosphere
      */
     public static CreateIcoSphere(name: string, options: { radius?: number, flat?: boolean, subdivisions?: number, sideOrientation?: number, updatable?: boolean }, scene: Scene): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     /**
@@ -3371,7 +3372,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
      * @returns a new Mesh
      */
     public static CreateDecal(name: string, sourceMesh: AbstractMesh, position: Vector3, normal: Vector3, size: Vector3, angle: number): Mesh {
-        throw "Import MeshBuilder before creating meshes.";
+        throw _DevTools.WarnImport("MeshBuilder");
     }
 
     // Skeletons

+ 17 - 16
src/Meshes/mesh.vertexData.ts

@@ -1,6 +1,7 @@
 import { Nullable, FloatArray, IndicesArray } from "../types";
 import { Matrix, Vector3, Vector2, Color3, Color4, Vector4 } from "../Maths/math";
 import { VertexBuffer } from "../Meshes/buffer";
+import { _DevTools } from '../Misc/devTools';
 
 declare type Geometry = import("../Meshes/geometry").Geometry;
 declare type Mesh = import("../Meshes/mesh").Mesh;
@@ -768,7 +769,7 @@ export class VertexData {
      * @returns the VertexData of the ribbon
      */
     public static CreateRibbon(options: { pathArray: Vector3[][], closeArray?: boolean, closePath?: boolean, offset?: number, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4, invertUV?: boolean, uvs?: Vector2[], colors?: Color4[] }): VertexData {
-        throw "Import Meshes/Builders/ribbonBuilder before trying to create ribbons.";
+        throw _DevTools.WarnImport("ribbonBuilder");
     }
 
     /**
@@ -786,7 +787,7 @@ export class VertexData {
      * @returns the VertexData of the box
      */
     public static CreateBox(options: { size?: number, width?: number, height?: number, depth?: number, faceUV?: Vector4[], faceColors?: Color4[], sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }): VertexData {
-        throw "Import Meshes/Builders/boxBuilder before trying to create boxes.";
+        throw _DevTools.WarnImport("boxBuilder");
     }
 
     /**
@@ -805,7 +806,7 @@ export class VertexData {
      * @returns the VertexData of the ellipsoid
      */
     public static CreateSphere(options: { segments?: number, diameter?: number, diameterX?: number, diameterY?: number, diameterZ?: number, arc?: number, slice?: number, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }): VertexData {
-        throw "Import Meshes/Builders/sphereBuilder before trying to create spheres.";
+        throw _DevTools.WarnImport("sphereBuilder");
     }
 
     /**
@@ -828,7 +829,7 @@ export class VertexData {
      * @returns the VertexData of the cylinder, cone or prism
      */
     public static CreateCylinder(options: { height?: number, diameterTop?: number, diameterBottom?: number, diameter?: number, tessellation?: number, subdivisions?: number, arc?: number, faceColors?: Color4[], faceUV?: Vector4[], hasRings?: boolean, enclose?: boolean, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }): VertexData {
-        throw "Import Meshes/Builders/cylinderBuilder before trying to create cylinders.";
+        throw _DevTools.WarnImport("cylinderBuilder");
     }
 
     /**
@@ -843,7 +844,7 @@ export class VertexData {
      * @returns the VertexData of the torus
      */
     public static CreateTorus(options: { diameter?: number, thickness?: number, tessellation?: number, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }): VertexData {
-        throw "Import Meshes/Builders/torusBuilder before trying to create torus.";
+        throw _DevTools.WarnImport("torusBuilder");
     }
 
     /**
@@ -854,7 +855,7 @@ export class VertexData {
      * @returns the VertexData of the LineSystem
      */
     public static CreateLineSystem(options: { lines: Vector3[][], colors?: Nullable<Color4[][]> }): VertexData {
-        throw "Import Meshes/Builders/linesBuilder before trying to create lines.";
+        throw _DevTools.WarnImport("linesBuilder");
     }
 
     /**
@@ -867,7 +868,7 @@ export class VertexData {
      * @returns the VertexData for the DashedLines
      */
     public static CreateDashedLines(options: { points: Vector3[], dashSize?: number, gapSize?: number, dashNb?: number }): VertexData {
-        throw "Import Meshes/Builders/linesBuilder before trying to create dashed lines.";
+        throw _DevTools.WarnImport("linesBuilder");
     }
 
     /**
@@ -879,7 +880,7 @@ export class VertexData {
      * @returns the VertexData of the Ground
      */
     public static CreateGround(options: { width?: number, height?: number, subdivisions?: number, subdivisionsX?: number, subdivisionsY?: number }): VertexData {
-        throw "Import Meshes/Builders/groundBuilder before trying to create grounds.";
+        throw _DevTools.WarnImport("groundBuilder");
     }
 
     /**
@@ -894,7 +895,7 @@ export class VertexData {
      * @returns the VertexData of the TiledGround
      */
     public static CreateTiledGround(options: { xmin: number, zmin: number, xmax: number, zmax: number, subdivisions?: { w: number; h: number; }, precision?: { w: number; h: number; } }): VertexData {
-        throw "Import Meshes/Builders/groundBuilder before trying to create grounds.";
+        throw _DevTools.WarnImport("groundBuilder");
     }
 
     /**
@@ -913,7 +914,7 @@ export class VertexData {
      * @returns the VertexData of the Ground designed from a heightmap
      */
     public static CreateGroundFromHeightMap(options: { width: number, height: number, subdivisions: number, minHeight: number, maxHeight: number, colorFilter: Color3, buffer: Uint8Array, bufferWidth: number, bufferHeight: number, alphaFilter: number }): VertexData {
-        throw "Import Meshes/Builders/groundBuilder before trying to create grounds.";
+        throw _DevTools.WarnImport("groundBuilder");
     }
 
     /**
@@ -928,7 +929,7 @@ export class VertexData {
      * @returns the VertexData of the box
      */
     public static CreatePlane(options: { size?: number, width?: number, height?: number, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }): VertexData {
-        throw "Import Meshes/Builders/planeBuilder before trying to create planes.";
+        throw _DevTools.WarnImport("planeBuilder");
     }
 
     /**
@@ -943,7 +944,7 @@ export class VertexData {
      * @returns the VertexData of the box
      */
     public static CreateDisc(options: { radius?: number, tessellation?: number, arc?: number, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }): VertexData {
-        throw "Import Meshes/Builders/discBuilder before trying to create discs.";
+        throw _DevTools.WarnImport("discBuilder");
     }
 
     /**
@@ -958,7 +959,7 @@ export class VertexData {
      * @returns the VertexData of the Polygon
      */
     public static CreatePolygon(polygon: Mesh, sideOrientation: number, fUV?: Vector4[], fColors?: Color4[], frontUVs?: Vector4, backUVs?: Vector4): VertexData {
-        throw "Import Meshes/Builders/polygonBuilder before trying to create polygons.";
+        throw _DevTools.WarnImport("polygonBuilder");
     }
 
     /**
@@ -976,7 +977,7 @@ export class VertexData {
      * @returns the VertexData of the IcoSphere
      */
     public static CreateIcoSphere(options: { radius?: number, radiusX?: number, radiusY?: number, radiusZ?: number, flat?: boolean, subdivisions?: number, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }): VertexData {
-        throw "Import Meshes/Builders/icoSphereBuilder before trying to create icoSpheres.";
+        throw _DevTools.WarnImport("icoSphereBuilder");
     }
 
     // inspired from // http://stemkoski.github.io/Three.js/Polyhedra.html
@@ -1001,7 +1002,7 @@ export class VertexData {
      * @returns the VertexData of the Polyhedron
      */
     public static CreatePolyhedron(options: { type?: number, size?: number, sizeX?: number, sizeY?: number, sizeZ?: number, custom?: any, faceUV?: Vector4[], faceColors?: Color4[], flat?: boolean, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }): VertexData {
-        throw "Import Meshes/Builders/polyhedronBuilder before trying to create polyhedrons.";
+        throw _DevTools.WarnImport("polyhedronBuilder");
     }
 
     // based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3D/src/away3d/primitives/TorusKnot.as?spec=svn2473&r=2473
@@ -1020,7 +1021,7 @@ export class VertexData {
      * @returns the VertexData of the Torus Knot
      */
     public static CreateTorusKnot(options: { radius?: number, tube?: number, radialSegments?: number, tubularSegments?: number, p?: number, q?: number, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }): VertexData {
-        throw "Import Meshes/Builders/torusKnotBuilder before trying to create torusKnots.";
+        throw _DevTools.WarnImport("torusKnotBuilder");
     }
 
     // Tools

+ 1 - 1
src/Meshes/subMesh.ts

@@ -4,7 +4,6 @@ import { Matrix, Vector3, Plane } from "../Maths/math";
 import { Engine } from "../Engines/engine";
 import { VertexBuffer } from "./buffer";
 import { IntersectionInfo } from "../Collisions/intersectionInfo";
-import { Ray } from "../Culling/ray";
 import { ICullable, BoundingInfo } from "../Culling/boundingInfo";
 import { Effect } from "../Materials/effect";
 import { Constants } from "../Engines/constants";
@@ -15,6 +14,7 @@ declare type MaterialDefines = import("../Materials/materialDefines").MaterialDe
 declare type MultiMaterial = import("../Materials/multiMaterial").MultiMaterial;
 declare type AbstractMesh = import("./abstractMesh").AbstractMesh;
 declare type Mesh = import("./mesh").Mesh;
+declare type Ray = import("../Culling/ray").Ray;
 
 /**
  * Base class for submeshes

+ 5 - 4
src/Misc/decorators.ts

@@ -1,6 +1,7 @@
 import { Tags } from "../Misc/tags";
 import { Nullable } from "../types";
 import { Color4, Quaternion, Color3, Vector2, Vector3 } from "../Maths/math";
+import { _DevTools } from './devTools';
 
 declare type Scene = import("../scene").Scene;
 declare type Camera = import("../Cameras/camera").Camera;
@@ -209,22 +210,22 @@ export function serializeAsCameraReference(sourceName?: string) {
 export class SerializationHelper {
     /** hidden */
     public static _ImageProcessingConfigurationParser = (sourceProperty: any): ImageProcessingConfiguration => {
-        throw "ImageProcessingConfiguration needs to be imported before being deserialized.";
+        throw _DevTools.WarnImport("ImageProcessingConfiguration");
     }
 
     /** hidden */
     public static _FresnelParametersParser = (sourceProperty: any): FresnelParameters => {
-        throw "FresnelParameters needs to be imported before being deserialized.";
+        throw _DevTools.WarnImport("FresnelParameters");
     }
 
     /** hidden */
     public static _ColorCurvesParser = (sourceProperty: any): ColorCurves => {
-        throw "ColorCurves needs to be imported before being deserialized.";
+        throw _DevTools.WarnImport("ColorCurves");
     }
 
     /** hidden */
     public static _TextureParser = (sourceProperty: any, scene: Scene, rootUrl: string): Nullable<BaseTexture> => {
-        throw "Texture needs to be imported before being deserialized.";
+        throw _DevTools.WarnImport("Texture");
     }
 
     /**

+ 6 - 0
src/Misc/devTools.ts

@@ -0,0 +1,6 @@
+/** @hidden */
+export class _DevTools {
+    public static WarnImport(name: string) {
+        return `${name} needs to be imported before as it contains a side-effect required by your code.`;
+    }
+}

+ 3 - 2
src/Misc/tools.ts

@@ -10,6 +10,7 @@ import { Logger } from "./logger";
 import { _TypeStore } from "./typeStore";
 import { DeepCopier } from "./deepCopier";
 import { PrecisionDate } from './precisionDate';
+import { _DevTools } from './devTools';
 
 declare type Camera = import("../Cameras/camera").Camera;
 declare type Engine = import("../Engines/engine").Engine;
@@ -1346,7 +1347,7 @@ export class Tools {
      * Check your browser for supported MIME types
      */
     public static CreateScreenshot(engine: Engine, camera: Camera, size: any, successCallback?: (data: string) => void, mimeType: string = "image/png"): void {
-        throw "Import ScreenshotTools before creating screenshot.";
+        throw _DevTools.WarnImport("ScreenshotTools");
     }
 
     /**
@@ -1369,7 +1370,7 @@ export class Tools {
      * @param fileName A name for for the downloaded file.
      */
     public static CreateScreenshotUsingRenderTarget(engine: Engine, camera: Camera, size: any, successCallback?: (data: string) => void, mimeType: string = "image/png", samples: number = 1, antialiasing: boolean = false, fileName?: string): void {
-        throw "Import ScreenshotTools before creating screenshot.";
+        throw _DevTools.WarnImport("ScreenshotTools");
     }
 
     /**

+ 2 - 1
src/Particles/subEmitter.ts

@@ -1,6 +1,7 @@
 import { Vector3 } from "../Maths/math";
 import { AbstractMesh } from "../Meshes/abstractMesh";
 import { Mesh } from "../Meshes/mesh";
+import { _DevTools } from '../Misc/devTools';
 
 declare type Scene = import("../scene").Scene;
 declare type ParticleSystem = import("../Particles/particleSystem").ParticleSystem;
@@ -102,7 +103,7 @@ export class SubEmitter {
 
     /** @hidden */
     public static _ParseParticleSystem(system: any, scene: Scene, rootUrl: string): ParticleSystem {
-        throw "Import ParseParticle before parsing SubEmitter.";
+        throw _DevTools.WarnImport("ParseParticle");
     }
 
     /**

+ 2 - 1
src/Physics/physicsEngine.ts

@@ -3,6 +3,7 @@ import { Vector3 } from "../Maths/math";
 import { IPhysicsEngine, PhysicsImpostorJoint, IPhysicsEnginePlugin } from "./IPhysicsEngine";
 import { PhysicsImpostor, IPhysicsEnabledObject } from "./physicsImpostor";
 import { PhysicsJoint } from "./physicsJoint";
+import { _DevTools } from '../Misc/devTools';
 
 /**
  * Class used to control physics engine
@@ -27,7 +28,7 @@ export class PhysicsEngine implements IPhysicsEngine {
      * @returns The default physics plugin
      */
     public static DefaultPluginFactory(): IPhysicsEnginePlugin {
-        throw "Import CannonJSPlugin or Fill DefaultPluginFactory static property on PhysicsEngine before relying on default physics plugin.";
+        throw _DevTools.WarnImport("CannonJSPlugin");
     }
 
     /**

+ 1 - 0
src/Physics/physicsHelper.ts

@@ -10,6 +10,7 @@ import { Scene } from "../scene";
 import { IPhysicsEngine } from "./IPhysicsEngine";
 import { PhysicsEngine } from "./physicsEngine";
 import { PhysicsImpostor } from "./physicsImpostor";
+
 /**
  * A helper for physics simulations
  * @see https://doc.babylonjs.com/how_to/using_the_physics_engine

+ 2 - 1
src/Rendering/depthRenderer.ts

@@ -13,6 +13,7 @@ import { Constants } from "../Engines/constants";
 
 import "../Shaders/depth.fragment";
 import "../Shaders/depth.vertex";
+import { _DevTools } from '../Misc/devTools';
 
 /**
  * This represents a depth renderer in Babylon.
@@ -35,7 +36,7 @@ export class DepthRenderer {
 
     /** @hidden */
     public static _SceneComponentInitialization: (scene: Scene) => void = (_) => {
-        throw "Import DepthRendererSceneComponent before creating DepthRenderer.";
+        throw _DevTools.WarnImport("DepthRendererSceneComponent");
     }
 
     /**

+ 2 - 1
src/Rendering/geometryBufferRenderer.ts

@@ -12,6 +12,7 @@ import { Scene } from "../scene";
 
 import "../Shaders/geometry.fragment";
 import "../Shaders/geometry.vertex";
+import { _DevTools } from '../Misc/devTools';
 
 /**
  * This renderer is helpfull to fill one of the render target with a geometry buffer.
@@ -124,7 +125,7 @@ export class GeometryBufferRenderer {
 
     /** @hidden */
     public static _SceneComponentInitialization: (scene: Scene) => void = (_) => {
-        throw "Import GeometryBufferRendererSceneComponent before creating GeometryBufferRenderer.";
+        throw _DevTools.WarnImport("GeometryBufferRendererSceneComponent");
     }
 
     /**

+ 1 - 1
src/Sprites/spriteManager.ts

@@ -6,7 +6,6 @@ import { VertexBuffer } from "../Meshes/buffer";
 import { Vector3 } from "../Maths/math";
 import { Sprite } from "./sprite";
 import { SpriteSceneComponent } from "./spriteSceneComponent";
-import { Ray } from "../Culling/ray";
 import { PickingInfo } from "../Collisions/pickingInfo";
 import { Camera } from "../Cameras/camera";
 import { Texture } from "../Materials/Textures/texture";
@@ -17,6 +16,7 @@ import { Constants } from "../Engines/constants";
 
 import "../Shaders/sprites.fragment";
 import "../Shaders/sprites.vertex";
+declare type Ray = import("../Culling/ray").Ray;
 
 /**
  * Defines the minimum interface to fullfil in order to be a sprite manager.

+ 2 - 1
src/node.ts

@@ -6,6 +6,7 @@ import { IBehaviorAware, Behavior } from "./Behaviors/behavior";
 import { serialize } from "./Misc/decorators";
 import { Observable, Observer } from "./Misc/observable";
 import { EngineStore } from "./Engines/engineStore";
+import { _DevTools } from './Misc/devTools';
 
 declare type Animatable = import("./Animations/animatable").Animatable;
 declare type AnimationPropertiesOverride = import("./Animations/animationPropertiesOverride").AnimationPropertiesOverride;
@@ -24,7 +25,7 @@ export type NodeConstructor = (name: string, scene: Scene, options?: any) => ()
 export class Node implements IBehaviorAware<Node> {
     /** @hidden */
     public static _AnimationRangeFactory = (name: string, from: number, to: number): AnimationRange => {
-        throw "AnimationRange needs to be imported from animation before being created.";
+        throw _DevTools.WarnImport("AnimationRange");
     }
 
     private static _NodeConstructors: { [key: string]: any } = {};

+ 12 - 174
src/scene.ts

@@ -37,7 +37,6 @@ import { IOfflineProvider } from "./Offline/IOfflineProvider";
 import { RenderingGroupInfo, RenderingManager, IRenderingManagerAutoClearSetup } from "./Rendering/renderingManager";
 import { ISceneComponent, ISceneSerializableComponent, Stage, SimpleStageAction, RenderTargetsStageAction, RenderTargetStageAction, MeshStageAction, EvaluateSubMeshStageAction, ActiveMeshStageAction, CameraStageAction, RenderingGroupStageAction, RenderingMeshStageAction, PointerMoveStageAction, PointerUpDownStageAction } from "./sceneComponent";
 import { Engine } from "./Engines/engine";
-import { Ray } from "./Culling/ray";
 import { Node } from "./node";
 import { MorphTarget } from "./Morph/morphTarget";
 import { Constants } from "./Engines/constants";
@@ -45,7 +44,9 @@ import { DomManagement } from "./Misc/domManagement";
 import { Logger } from "./Misc/logger";
 import { EngineStore } from "./Engines/engineStore";
 import { AbstractActionManager } from './Actions/abstractActionManager';
+import { _DevTools } from './Misc/devTools';
 
+declare type Ray = import("./Culling/ray").Ray;
 declare type Animation = import("./Animations/animation").Animation;
 declare type Animatable = import("./Animations/animatable").Animatable;
 declare type AnimationGroup = import("./Animations/animationGroup").AnimationGroup;
@@ -152,7 +153,7 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @returns The default material
      */
     public static DefaultMaterialFactory(scene: Scene): Material {
-        throw "Import StandardMaterial or set DefaultMaterialFactory static property on scene before relying on default material creation.";
+        throw _DevTools.WarnImport("StandardMaterial");
     }
 
     /**
@@ -160,7 +161,7 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @returns The collision coordinator
      */
     public static CollisionCoordinatorFactory(): ICollisionCoordinator {
-        throw "Import DefaultCollisionCoordinator or set CollisionCoordinatorFactory static property on scene to enable collisions.";
+        throw _DevTools.WarnImport("DefaultCollisionCoordinator");
     }
 
     // Members
@@ -1092,8 +1093,6 @@ export class Scene extends AbstractScene implements IAnimatable {
     private _sceneUbo: UniformBuffer;
     private _alternateSceneUbo: UniformBuffer;
 
-    private _pickWithRayInverseMatrix: Matrix;
-
     private _viewMatrix: Matrix;
     private _projectionMatrix: Matrix;
     private _alternateViewMatrix: Matrix;
@@ -4690,11 +4689,7 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @returns a Ray
      */
     public createPickingRay(x: number, y: number, world: Matrix, camera: Nullable<Camera>, cameraViewSpace = false): Ray {
-        let result = Ray.Zero();
-
-        this.createPickingRayToRef(x, y, world, result, camera, cameraViewSpace);
-
-        return result;
+        throw _DevTools.WarnImport("Ray");
     }
 
     /**
@@ -4708,25 +4703,7 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @returns the current scene
      */
     public createPickingRayToRef(x: number, y: number, world: Matrix, result: Ray, camera: Nullable<Camera>, cameraViewSpace = false): Scene {
-        var engine = this._engine;
-
-        if (!camera) {
-            if (!this.activeCamera) {
-                throw new Error("Active camera not set");
-            }
-
-            camera = this.activeCamera;
-        }
-
-        var cameraViewport = camera.viewport;
-        var viewport = cameraViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
-
-        // Moving coordinates to local viewport world
-        x = x / this._engine.getHardwareScalingLevel() - viewport.x;
-        y = y / this._engine.getHardwareScalingLevel() - (this._engine.getRenderHeight() - viewport.y - viewport.height);
-
-        result.update(x, y, viewport.width, viewport.height, world ? world : Matrix.IdentityReadOnly, cameraViewSpace ? Matrix.IdentityReadOnly : camera.getViewMatrix(), camera.getProjectionMatrix());
-        return this;
+        throw _DevTools.WarnImport("Ray");
     }
 
     /**
@@ -4737,11 +4714,7 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @returns a Ray
      */
     public createPickingRayInCameraSpace(x: number, y: number, camera?: Camera): Ray {
-        let result = Ray.Zero();
-
-        this.createPickingRayInCameraSpaceToRef(x, y, result, camera);
-
-        return result;
+        throw _DevTools.WarnImport("Ray");
     }
 
     /**
@@ -4753,104 +4726,9 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @returns the current scene
      */
     public createPickingRayInCameraSpaceToRef(x: number, y: number, result: Ray, camera?: Camera): Scene {
-        if (!PickingInfo) {
-            return this;
-        }
-
-        var engine = this._engine;
-
-        if (!camera) {
-            if (!this.activeCamera) {
-                throw new Error("Active camera not set");
-            }
-
-            camera = this.activeCamera;
-        }
-
-        var cameraViewport = camera.viewport;
-        var viewport = cameraViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
-        var identity = Matrix.Identity();
-
-        // Moving coordinates to local viewport world
-        x = x / this._engine.getHardwareScalingLevel() - viewport.x;
-        y = y / this._engine.getHardwareScalingLevel() - (this._engine.getRenderHeight() - viewport.y - viewport.height);
-        result.update(x, y, viewport.width, viewport.height, identity, identity, camera.getProjectionMatrix());
-        return this;
+        throw _DevTools.WarnImport("Ray");
     }
 
-    private _internalPick(rayFunction: (world: Matrix) => Ray, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean): Nullable<PickingInfo> {
-        if (!PickingInfo) {
-            return null;
-        }
-
-        var pickingInfo = null;
-
-        for (var meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
-            var mesh = this.meshes[meshIndex];
-
-            if (predicate) {
-                if (!predicate(mesh)) {
-                    continue;
-                }
-            } else if (!mesh.isEnabled() || !mesh.isVisible || !mesh.isPickable) {
-                continue;
-            }
-
-            var world = mesh.getWorldMatrix();
-            var ray = rayFunction(world);
-
-            var result = mesh.intersects(ray, fastCheck);
-            if (!result || !result.hit) {
-                continue;
-            }
-
-            if (!fastCheck && pickingInfo != null && result.distance >= pickingInfo.distance) {
-                continue;
-            }
-
-            pickingInfo = result;
-
-            if (fastCheck) {
-                break;
-            }
-        }
-
-        return pickingInfo || new PickingInfo();
-    }
-
-    private _internalMultiPick(rayFunction: (world: Matrix) => Ray, predicate?: (mesh: AbstractMesh) => boolean): Nullable<PickingInfo[]> {
-        if (!PickingInfo) {
-            return null;
-        }
-        var pickingInfos = new Array<PickingInfo>();
-
-        for (var meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
-            var mesh = this.meshes[meshIndex];
-
-            if (predicate) {
-                if (!predicate(mesh)) {
-                    continue;
-                }
-            } else if (!mesh.isEnabled() || !mesh.isVisible || !mesh.isPickable) {
-                continue;
-            }
-
-            var world = mesh.getWorldMatrix();
-            var ray = rayFunction(world);
-
-            var result = mesh.intersects(ray, false);
-            if (!result || !result.hit) {
-                continue;
-            }
-
-            pickingInfos.push(result);
-        }
-
-        return pickingInfos;
-    }
-
-    private _tempPickingRay: Nullable<Ray> = Ray ? Ray.Zero() : null;
-
     /** Launch a ray to try to pick a mesh in the scene
      * @param x position on screen
      * @param y position on screen
@@ -4860,21 +4738,9 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @returns a PickingInfo
      */
     public pick(x: number, y: number, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean, camera?: Nullable<Camera>): Nullable<PickingInfo> {
-        if (!PickingInfo) {
-            return null;
-        }
-        var result = this._internalPick((world) => {
-            this.createPickingRayToRef(x, y, world, this._tempPickingRay!, camera || null);
-            return this._tempPickingRay!;
-        }, predicate, fastCheck);
-        if (result) {
-            result.ray = this.createPickingRay(x, y, Matrix.Identity(), camera || null);
-        }
-        return result;
+        throw _DevTools.WarnImport("Ray");
     }
 
-    private _cachedRayForTransform: Ray;
-
     /** Use the given ray to pick a mesh in the scene
      * @param ray The ray to use to pick meshes
      * @param predicate Predicate function used to determine eligible meshes. Can be set to null. In this case, a mesh must have isPickable set to true
@@ -4882,23 +4748,7 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @returns a PickingInfo
      */
     public pickWithRay(ray: Ray, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean): Nullable<PickingInfo> {
-        var result = this._internalPick((world) => {
-            if (!this._pickWithRayInverseMatrix) {
-                this._pickWithRayInverseMatrix = Matrix.Identity();
-            }
-            world.invertToRef(this._pickWithRayInverseMatrix);
-
-            if (!this._cachedRayForTransform) {
-                this._cachedRayForTransform = Ray.Zero();
-            }
-
-            Ray.TransformToRef(ray, this._pickWithRayInverseMatrix, this._cachedRayForTransform);
-            return this._cachedRayForTransform;
-        }, predicate, fastCheck);
-        if (result) {
-            result.ray = ray;
-        }
-        return result;
+        throw _DevTools.WarnImport("Ray");
     }
 
     /**
@@ -4910,7 +4760,7 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @returns an array of PickingInfo
      */
     public multiPick(x: number, y: number, predicate?: (mesh: AbstractMesh) => boolean, camera?: Camera): Nullable<PickingInfo[]> {
-        return this._internalMultiPick((world) => this.createPickingRay(x, y, world, camera || null), predicate);
+        throw _DevTools.WarnImport("Ray");
     }
 
     /**
@@ -4920,19 +4770,7 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @returns an array of PickingInfo
      */
     public multiPickWithRay(ray: Ray, predicate: (mesh: AbstractMesh) => boolean): Nullable<PickingInfo[]> {
-        return this._internalMultiPick((world) => {
-            if (!this._pickWithRayInverseMatrix) {
-                this._pickWithRayInverseMatrix = Matrix.Identity();
-            }
-            world.invertToRef(this._pickWithRayInverseMatrix);
-
-            if (!this._cachedRayForTransform) {
-                this._cachedRayForTransform = Ray.Zero();
-            }
-
-            Ray.TransformToRef(ray, this._pickWithRayInverseMatrix, this._cachedRayForTransform);
-            return this._cachedRayForTransform;
-        }, predicate);
+        throw _DevTools.WarnImport("Ray");
     }
 
     /**