浏览代码

Merge pull request #5432 from barroij/DeepImmutable

Add a DeepImmutable<t> type
David Catuhe 6 年之前
父节点
当前提交
26564c2d5c

+ 3 - 2
dist/preview release/what's new.md

@@ -80,6 +80,7 @@
 - Fixed `Matrix.toNormalMatrix`function ([barroij](https://github.com/barroij))
 - Add missing effect layer to asset container ([TrevorDev](https://github.com/TrevorDev))
 - Fixed effect layer compatibility with multi materials ([Sebavan](https://github.com/Sebavan))
+- Added a `DeepImmutable<T>` type to specifiy that a referenced object should be considered recursively immutable, meaning that all its properties are `readonly` and that if a property is a reference to an object, this object is also recursively immutable. ([barroij](https://github.com/barroij))
 
 ### Viewer
 
@@ -90,8 +91,8 @@
 - `Database.IDBStorageEnabled` is now false by default ([Deltakosh](https://github.com/deltakosh))
 - `Database.openAsync` was renamed by `Database.open` ([Deltakosh](https://github.com/deltakosh))
 - `scene.database` was renamed to `scene.offlineProvider` ([Deltakosh](https://github.com/deltakosh))
-- `BoundingBox.setWorldMatrix` was removed. `BoundingBox.getWorldMatrix` now returns a `Readonly<Matrix>` ([barroij](https://github.com/barroij))
-- `Matrix`'s accessor `m` and method `toArray` and `asArray` now returns a `Readonly<Float32Array>` as the matrix underlying array is not supposed to be modified manually from the outside of the class ([barroij](https://github.com/barroij))
+- `BoundingBox.setWorldMatrix` was removed. `BoundingBox.getWorldMatrix` now returns a `DeepImmutable<Matrix>` ([barroij](https://github.com/barroij))
+- `Matrix`'s accessor `m` and method `toArray` and `asArray` now returns a `DeepImmutable<Float32Array>` as the matrix underlying array is not supposed to be modified manually from the outside of the class ([barroij](https://github.com/barroij))
 - Removed some deprecated (flagged since 3.0) properties and functions ([Deltakosh](https://github.com/deltakosh))
   - `scene.getInterFramePerfCounter()`: use SceneInstrumentation class instead
   - `scene.interFramePerfCounter`: use SceneInstrumentation class instead

+ 5 - 5
src/Animations/babylon.runtimeAnimation.ts

@@ -3,19 +3,19 @@ module BABYLON {
     // Static values to help the garbage collector
 
     // Quaternion
-    const _staticOffsetValueQuaternion: Readonly<Quaternion> = Object.freeze(new Quaternion(0, 0, 0, 0));
+    const _staticOffsetValueQuaternion: DeepImmutable<Quaternion> = Object.freeze(new Quaternion(0, 0, 0, 0));
 
     // Vector3
-    const _staticOffsetValueVector3: Readonly<Vector3> = Object.freeze(Vector3.Zero());
+    const _staticOffsetValueVector3: DeepImmutable<Vector3> = Object.freeze(Vector3.Zero());
 
     // Vector2
-    const _staticOffsetValueVector2: Readonly<Vector2> = Object.freeze(Vector2.Zero());
+    const _staticOffsetValueVector2: DeepImmutable<Vector2> = Object.freeze(Vector2.Zero());
 
     // Size
-    const _staticOffsetValueSize: Readonly<Size> = Object.freeze(Size.Zero());
+    const _staticOffsetValueSize: DeepImmutable<Size> = Object.freeze(Size.Zero());
 
     // Color3
-    const _staticOffsetValueColor3: Readonly<Color3> = Object.freeze(Color3.Black());
+    const _staticOffsetValueColor3: DeepImmutable<Color3> = Object.freeze(Color3.Black());
 
     /**
      * Defines a runtime animation

+ 14 - 14
src/Culling/babylon.boundingBox.ts

@@ -48,7 +48,7 @@ module BABYLON {
          */
         public readonly maximum: Vector3 = Vector3.Zero();
 
-        private _worldMatrix: Readonly<Matrix>;
+        private _worldMatrix: DeepImmutable<Matrix>;
         private static readonly TmpVector3 = Tools.BuildArray(3, Vector3.Zero);
 
         /**
@@ -62,7 +62,7 @@ module BABYLON {
          * @param max defines the maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        constructor(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
+        constructor(min: DeepImmutable<Vector3>, max: DeepImmutable<Vector3>, worldMatrix?: DeepImmutable<Matrix>) {
             this.reConstruct(min, max, worldMatrix);
         }
 
@@ -74,7 +74,7 @@ module BABYLON {
          * @param max defines the new maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        public reConstruct(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
+        public reConstruct(min: DeepImmutable<Vector3>, max: DeepImmutable<Vector3>, worldMatrix?: DeepImmutable<Matrix>) {
             const minX = min.x, minY = min.y, minZ = min.z, maxX = max.x, maxY = max.y, maxZ = max.z;
             const vectors = this.vectors;
 
@@ -121,12 +121,12 @@ module BABYLON {
          * Gets the world matrix of the bounding box
          * @returns a matrix
          */
-        public getWorldMatrix(): Readonly<Matrix> {
+        public getWorldMatrix(): DeepImmutable<Matrix> {
             return this._worldMatrix;
         }
 
         /** @hidden */
-        public _update(world: Readonly<Matrix>): void {
+        public _update(world: DeepImmutable<Matrix>): void {
             const minWorld = this.minimumWorld;
             const maxWorld = this.maximumWorld;
             const directions = this.directions;
@@ -172,7 +172,7 @@ module BABYLON {
          * @param frustumPlanes defines the frustum planes to test
          * @returns true if there is an intersection
          */
-        public isInFrustum(frustumPlanes: Array<Readonly<Plane>>): boolean {
+        public isInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
             return BoundingBox.IsInFrustum(this.vectorsWorld, frustumPlanes);
         }
 
@@ -181,7 +181,7 @@ module BABYLON {
          * @param frustumPlanes defines the frustum planes to test
          * @returns true if there is an inclusion
          */
-        public isCompletelyInFrustum(frustumPlanes: Array<Readonly<Plane>>): boolean {
+        public isCompletelyInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
             return BoundingBox.IsCompletelyInFrustum(this.vectorsWorld, frustumPlanes);
         }
 
@@ -190,7 +190,7 @@ module BABYLON {
          * @param point defines the point to test
          * @returns true if the point is inside the bounding box
          */
-        public intersectsPoint(point: Readonly<Vector3>): boolean {
+        public intersectsPoint(point: DeepImmutable<Vector3>): boolean {
             const min = this.minimumWorld;
             const max = this.maximumWorld;
             const minX = min.x, minY = min.y, minZ = min.z, maxX = max.x, maxY = max.y, maxZ = max.z;
@@ -217,7 +217,7 @@ module BABYLON {
          * @param sphere defines the sphere to test
          * @returns true if there is an intersection
          */
-        public intersectsSphere(sphere: Readonly<BoundingSphere>): boolean {
+        public intersectsSphere(sphere: DeepImmutable<BoundingSphere>): boolean {
             return BoundingBox.IntersectsSphere(this.minimumWorld, this.maximumWorld, sphere.centerWorld, sphere.radiusWorld);
         }
 
@@ -227,7 +227,7 @@ module BABYLON {
          * @param max defines the max vector to use
          * @returns true if there is an intersection
          */
-        public intersectsMinMax(min: Readonly<Vector3>, max: Readonly<Vector3>): boolean {
+        public intersectsMinMax(min: DeepImmutable<Vector3>, max: DeepImmutable<Vector3>): boolean {
             const myMin = this.minimumWorld;
             const myMax = this.maximumWorld;
             const myMinX = myMin.x, myMinY = myMin.y, myMinZ = myMin.z, myMaxX = myMax.x, myMaxY = myMax.y, myMaxZ = myMax.z;
@@ -255,7 +255,7 @@ module BABYLON {
          * @param box1 defines the second box to test
          * @returns true if there is an intersection
          */
-        public static Intersects(box0: BoundingBox, box1: BoundingBox): boolean {
+        public static Intersects(box0: DeepImmutable<BoundingBox>, box1: DeepImmutable<BoundingBox>): boolean {
             return box0.intersectsMinMax(box1.minimumWorld, box1.maximumWorld);
         }
 
@@ -267,7 +267,7 @@ module BABYLON {
          * @param sphereRadius defines the sphere radius
          * @returns true if there is an intersection
          */
-        public static IntersectsSphere(minPoint: Readonly<Vector3>, maxPoint: Readonly<Vector3>, sphereCenter: Readonly<Vector3>, sphereRadius: number): boolean {
+        public static IntersectsSphere(minPoint: DeepImmutable<Vector3>, maxPoint: DeepImmutable<Vector3>, sphereCenter: DeepImmutable<Vector3>, sphereRadius: number): boolean {
             const vector = BoundingBox.TmpVector3[0];
             Vector3.ClampToRef(sphereCenter, minPoint, maxPoint, vector);
             var num = Vector3.DistanceSquared(sphereCenter, vector);
@@ -280,7 +280,7 @@ module BABYLON {
          * @param frustumPlanes defines the frustum planes to test
          * @return true if there is an inclusion
          */
-        public static IsCompletelyInFrustum(boundingVectors: Array<Readonly<Vector3>>, frustumPlanes: Array<Readonly<Plane>>): boolean {
+        public static IsCompletelyInFrustum(boundingVectors: Array<DeepImmutable<Vector3>>, frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
             for (var p = 0; p < 6; ++p) {
                 const frustumPlane = frustumPlanes[p];
                 for (var i = 0; i < 8; ++i) {
@@ -298,7 +298,7 @@ module BABYLON {
          * @param frustumPlanes defines the frustum planes to test
          * @return true if there is an intersection
          */
-        public static IsInFrustum(boundingVectors: Array<Readonly<Vector3>>, frustumPlanes: Array<Readonly<Plane>>): boolean {
+        public static IsInFrustum(boundingVectors: Array<DeepImmutable<Vector3>>, frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
             for (var p = 0; p < 6; ++p) {
                 let canReturnFalse = true;
                 const frustumPlane = frustumPlanes[p];

+ 10 - 10
src/Culling/babylon.boundingInfo.ts

@@ -1,7 +1,7 @@
 module BABYLON {
     const _result0 = { min: 0, max: 0};
     const _result1 = { min: 0, max: 0};
-    const computeBoxExtents = (axis: Readonly<Vector3>, box: Readonly<BoundingBox>, result: {min: number, max: number}) => {
+    const computeBoxExtents = (axis: DeepImmutable<Vector3>, box: DeepImmutable<BoundingBox>, result: {min: number, max: number}) => {
         const p = Vector3.Dot(box.centerWorld, axis);
 
         const r0 = Math.abs(Vector3.Dot(box.directions[0], axis)) * box.extendSize.x;
@@ -13,7 +13,7 @@ module BABYLON {
         result.max = p + r;
     };
 
-    const axisOverlap = (axis: Vector3, box0: BoundingBox, box1: BoundingBox): boolean => {
+    const axisOverlap = (axis: DeepImmutable<Vector3>, box0: DeepImmutable<BoundingBox>, box1: DeepImmutable<BoundingBox>): boolean => {
         computeBoxExtents(axis, box0, _result0);
         computeBoxExtents(axis, box1, _result1);
         return !(_result0.min > _result1.max || _result1.min > _result0.max);
@@ -62,7 +62,7 @@ module BABYLON {
          * @param maximum max vector of the bounding box/sphere
          * @param worldMatrix defines the new world matrix
          */
-        constructor(minimum: Readonly<Vector3>, maximum: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
+        constructor(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, worldMatrix?: DeepImmutable<Matrix>) {
             this.boundingBox = new BoundingBox(minimum, maximum, worldMatrix);
             this.boundingSphere = new BoundingSphere(minimum, maximum, worldMatrix);
         }
@@ -73,7 +73,7 @@ module BABYLON {
          * @param max defines the new maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        public reConstruct(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
+        public reConstruct(min: DeepImmutable<Vector3>, max: DeepImmutable<Vector3>, worldMatrix?: DeepImmutable<Matrix>) {
             this.boundingBox.reConstruct(min, max, worldMatrix);
             this.boundingSphere.reConstruct(min, max, worldMatrix);
         }
@@ -108,7 +108,7 @@ module BABYLON {
          * Updates the bounding sphere and box
          * @param world world matrix to be used to update
          */
-        public update(world: Readonly<Matrix>) {
+        public update(world: DeepImmutable<Matrix>) {
             if (this._isLocked) {
                 return;
             }
@@ -122,7 +122,7 @@ module BABYLON {
          * @param extend New extend of the bounding info
          * @returns the current bounding info
          */
-        public centerOn(center: Readonly<Vector3>, extend: Readonly<Vector3>): BoundingInfo {
+        public centerOn(center: DeepImmutable<Vector3>, extend: DeepImmutable<Vector3>): BoundingInfo {
 
             const minimum = BoundingInfo.TmpVector3[0].copyFrom(center).subtractInPlace(extend);
             const maximum = BoundingInfo.TmpVector3[1].copyFrom(center).addInPlace(extend);
@@ -151,7 +151,7 @@ module BABYLON {
          * @param strategy defines the strategy to use for the culling (default is BABYLON.Scene.CULLINGSTRATEGY_STANDARD)
          * @returns true if the bounding info is in the frustum planes
          */
-        public isInFrustum(frustumPlanes: Array<Readonly<Plane>>, strategy: number = AbstractMesh.CULLINGSTRATEGY_STANDARD): boolean {
+        public isInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>, strategy: number = AbstractMesh.CULLINGSTRATEGY_STANDARD): boolean {
             if (!this.boundingSphere.isInFrustum(frustumPlanes)) {
                 return false;
             }
@@ -177,7 +177,7 @@ module BABYLON {
          * @param frustumPlanes Camera near/planes
          * @returns true if the object is in frustum otherwise false
          */
-        public isCompletelyInFrustum(frustumPlanes: Array<Readonly<Plane>>): boolean {
+        public isCompletelyInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
             return this.boundingBox.isCompletelyInFrustum(frustumPlanes);
         }
         /** @hidden */
@@ -191,7 +191,7 @@ module BABYLON {
          * @param point the point to check intersection with
          * @returns if the point intersects
          */
-        public intersectsPoint(point: Readonly<Vector3>): boolean {
+        public intersectsPoint(point: DeepImmutable<Vector3>): boolean {
             if (!this.boundingSphere.centerWorld) {
                 return false;
             }
@@ -214,7 +214,7 @@ module BABYLON {
          * @param precise if the intersection should be done using OBB
          * @returns if the bounding info intersects
          */
-        public intersects(boundingInfo: Readonly<BoundingInfo>, precise: boolean): boolean {
+        public intersects(boundingInfo: DeepImmutable<BoundingInfo>, precise: boolean): boolean {
             if (!BoundingSphere.Intersects(this.boundingSphere, boundingInfo.boundingSphere)) {
                 return false;
             }

+ 8 - 8
src/Culling/babylon.boundingSphere.ts

@@ -28,7 +28,7 @@ module BABYLON {
          */
         public readonly maximum = Vector3.Zero();
 
-        private _worldMatrix: Readonly<Matrix>;
+        private _worldMatrix: DeepImmutable<Matrix>;
         private static readonly TmpVector3 = Tools.BuildArray(3, Vector3.Zero);
 
         /**
@@ -37,7 +37,7 @@ module BABYLON {
          * @param max defines the maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        constructor(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
+        constructor(min: DeepImmutable<Vector3>, max: DeepImmutable<Vector3>, worldMatrix?: DeepImmutable<Matrix>) {
             this.reConstruct(min, max, worldMatrix);
         }
 
@@ -47,7 +47,7 @@ module BABYLON {
          * @param max defines the new maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        public reConstruct(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
+        public reConstruct(min: DeepImmutable<Vector3>, max: DeepImmutable<Vector3>, worldMatrix?: DeepImmutable<Matrix>) {
             this.minimum.copyFrom(min);
             this.maximum.copyFrom(max);
 
@@ -80,13 +80,13 @@ module BABYLON {
          * Gets the world matrix of the bounding box
          * @returns a matrix
          */
-        public getWorldMatrix(): Readonly<Matrix> {
+        public getWorldMatrix(): DeepImmutable<Matrix> {
             return this._worldMatrix;
         }
 
         // Methods
         /** @hidden */
-        public _update(worldMatrix: Readonly<Matrix>): void {
+        public _update(worldMatrix: DeepImmutable<Matrix>): void {
             if (!worldMatrix.isIdentity()) {
                 Vector3.TransformCoordinatesToRef(this.center, worldMatrix, this.centerWorld);
                 const tempVector = BoundingSphere.TmpVector3[0];
@@ -104,7 +104,7 @@ module BABYLON {
          * @param frustumPlanes defines the frustum planes to test
          * @returns true if there is an intersection
          */
-        public isInFrustum(frustumPlanes: Array<Readonly<Plane>>): boolean {
+        public isInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
             for (var i = 0; i < 6; i++) {
                 if (frustumPlanes[i].dotCoordinate(this.centerWorld) <= -this.radiusWorld) {
                     return false;
@@ -119,7 +119,7 @@ module BABYLON {
          * @param point defines the point to test
          * @returns true if the point is inside the bounding sphere
          */
-        public intersectsPoint(point: Readonly<Vector3>): boolean {
+        public intersectsPoint(point: DeepImmutable<Vector3>): boolean {
             const squareDistance = Vector3.DistanceSquared(this.centerWorld, point);
             if (this.radiusWorld * this.radiusWorld < squareDistance) {
                 return false;
@@ -135,7 +135,7 @@ module BABYLON {
          * @param sphere1 sphere 1
          * @returns true if the speres intersect
          */
-        public static Intersects(sphere0: Readonly<BoundingSphere>, sphere1: Readonly<BoundingSphere>): boolean {
+        public static Intersects(sphere0: DeepImmutable<BoundingSphere>, sphere1: DeepImmutable<BoundingSphere>): boolean {
             const squareDistance = Vector3.DistanceSquared(sphere0.centerWorld, sphere1.centerWorld);
             const radiusSum = sphere0.radiusWorld + sphere1.radiusWorld;
 

+ 14 - 14
src/Culling/babylon.ray.ts

@@ -29,7 +29,7 @@ module BABYLON {
          * @param intersectionTreshold extra extend to be added to the box in all direction
          * @returns if the box was hit
          */
-        public intersectsBoxMinMax(minimum: Vector3, maximum: Vector3, intersectionTreshold: number = 0): boolean {
+        public intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold: number = 0): boolean {
             const newMinimum = Ray.TmpVector3[0].copyFromFloats(minimum.x - intersectionTreshold, minimum.y - intersectionTreshold, minimum.z - intersectionTreshold);
             const newMaximum = Ray.TmpVector3[1].copyFromFloats(maximum.x + intersectionTreshold, maximum.y + intersectionTreshold, maximum.z + intersectionTreshold);
             var d = 0.0;
@@ -129,7 +129,7 @@ module BABYLON {
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @returns if the box was hit
          */
-        public intersectsBox(box: BoundingBox, intersectionTreshold: number = 0): boolean {
+        public intersectsBox(box: DeepImmutable<BoundingBox>, intersectionTreshold: number = 0): boolean {
             return this.intersectsBoxMinMax(box.minimum, box.maximum, intersectionTreshold);
         }
 
@@ -139,7 +139,7 @@ module BABYLON {
          * @param intersectionTreshold extra extend to be added to the BoundingSphere in all direction
          * @returns true if it hits the sphere
          */
-        public intersectsSphere(sphere: BoundingSphere, intersectionTreshold: number = 0): boolean {
+        public intersectsSphere(sphere: DeepImmutable<BoundingSphere>, intersectionTreshold: number = 0): boolean {
             var x = sphere.center.x - this.origin.x;
             var y = sphere.center.y - this.origin.y;
             var z = sphere.center.z - this.origin.z;
@@ -168,7 +168,7 @@ module BABYLON {
          * @param vertex2 triangle vertex
          * @returns intersection information if hit
          */
-        public intersectsTriangle(vertex0: Vector3, vertex1: Vector3, vertex2: Vector3): Nullable<IntersectionInfo> {
+        public intersectsTriangle(vertex0: DeepImmutable<Vector3>, vertex1: DeepImmutable<Vector3>, vertex2: DeepImmutable<Vector3>): Nullable<IntersectionInfo> {
             const edge1 = Ray.TmpVector3[0];
             const edge2 = Ray.TmpVector3[1];
             const pvec = Ray.TmpVector3[2];
@@ -216,7 +216,7 @@ module BABYLON {
          * @param plane the plane to check
          * @returns the distance away it was hit
          */
-        public intersectsPlane(plane: Plane): Nullable<number> {
+        public intersectsPlane(plane: DeepImmutable<Plane>): Nullable<number> {
             var distance: number;
             var result1 = Vector3.Dot(plane.normal, this.direction);
             if (Math.abs(result1) < 9.99999997475243E-07) {
@@ -243,7 +243,7 @@ module BABYLON {
          * @param fastCheck if only the bounding box should checked
          * @returns picking info of the intersecton
          */
-        public intersectsMesh(mesh: AbstractMesh, fastCheck?: boolean): PickingInfo {
+        public intersectsMesh(mesh: DeepImmutable<AbstractMesh>, fastCheck?: boolean): PickingInfo {
 
             var tm = Tmp.Matrix[0];
 
@@ -266,7 +266,7 @@ module BABYLON {
          * @param results array to store result in
          * @returns Array of picking infos
          */
-        public intersectsMeshes(meshes: Array<AbstractMesh>, fastCheck?: boolean, results?: Array<PickingInfo>): Array<PickingInfo> {
+        public intersectsMeshes(meshes: Array<DeepImmutable<AbstractMesh>>, fastCheck?: boolean, results?: Array<PickingInfo>): Array<PickingInfo> {
 
             if (results) {
                 results.length = 0;
@@ -288,7 +288,7 @@ module BABYLON {
 
         }
 
-        private _comparePickingInfo(pickingInfoA: PickingInfo, pickingInfoB: PickingInfo): number {
+        private _comparePickingInfo(pickingInfoA: DeepImmutable<PickingInfo>, pickingInfoB: DeepImmutable<PickingInfo>): number {
 
             if (pickingInfoA.distance < pickingInfoB.distance) {
                 return -1;
@@ -310,7 +310,7 @@ module BABYLON {
          * @param threshold the tolerance margin, if the ray doesn't intersect the segment but is close to the given threshold, the intersection is successful
          * @return the distance from the ray origin to the intersection point if there's intersection, or -1 if there's no intersection
          */
-        intersectionSegment(sega: Vector3, segb: Vector3, threshold: number): number {
+        intersectionSegment(sega: DeepImmutable<Vector3>, segb: DeepImmutable<Vector3>, threshold: number): number {
             const o = this.origin;
             const u =  Tmp.Vector3[0];
             const rsegb  = Tmp.Vector3[1];
@@ -408,7 +408,7 @@ module BABYLON {
          * @param projection projection matrix
          * @returns this ray updated
          */
-        public update(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Readonly<Matrix>, view: Readonly<Matrix>, projection: Readonly<Matrix>): Ray {
+        public update(x: number, y: number, viewportWidth: number, viewportHeight: number, world: DeepImmutable<Matrix>, view: DeepImmutable<Matrix>, projection: DeepImmutable<Matrix>): Ray {
             Vector3.UnprojectRayToRef(x, y, viewportWidth, viewportHeight, world, view, projection, this);
             return this;
         }
@@ -433,7 +433,7 @@ module BABYLON {
          * @param projection projection matrix
          * @returns new ray
          */
-        public static CreateNew(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Ray {
+        public static CreateNew(x: number, y: number, viewportWidth: number, viewportHeight: number, world: DeepImmutable<Matrix>, view: DeepImmutable<Matrix>, projection: DeepImmutable<Matrix>): Ray {
             let result = Ray.Zero();
 
             return result.update(x, y, viewportWidth, viewportHeight, world, view, projection);
@@ -447,7 +447,7 @@ module BABYLON {
         * @param world a matrix to transform the ray to. Default is the identity matrix.
         * @returns the new ray
         */
-        public static CreateNewFromTo(origin: Vector3, end: Vector3, world: Readonly<Matrix> = Matrix.IdentityReadOnly): Ray {
+        public static CreateNewFromTo(origin: DeepImmutable<Vector3>, end: DeepImmutable<Vector3>, world: DeepImmutable<Matrix> = Matrix.IdentityReadOnly): Ray {
             var direction = end.subtract(origin);
             var length = Math.sqrt((direction.x * direction.x) + (direction.y * direction.y) + (direction.z * direction.z));
             direction.normalize();
@@ -461,7 +461,7 @@ module BABYLON {
          * @param matrix matrix to apply
          * @returns the resulting new ray
          */
-        public static Transform(ray: Ray, matrix: Readonly<Matrix>): Ray {
+        public static Transform(ray: DeepImmutable<Ray>, matrix: DeepImmutable<Matrix>): Ray {
             var result = new Ray(new Vector3(0, 0, 0), new Vector3(0, 0, 0));
             Ray.TransformToRef(ray, matrix, result);
 
@@ -474,7 +474,7 @@ module BABYLON {
          * @param matrix matrix to apply
          * @param result ray to store result in
          */
-        public static TransformToRef(ray: Ray, matrix: Readonly<Matrix>, result: Ray): void {
+        public static TransformToRef(ray: DeepImmutable<Ray>, matrix: DeepImmutable<Matrix>, result: Ray): void {
             Vector3.TransformCoordinatesToRef(ray.origin, matrix, result.origin);
             Vector3.TransformNormalToRef(ray.direction, matrix, result.direction);
             result.length = ray.length;

文件差异内容过多而无法显示
+ 237 - 230
src/Math/babylon.math.ts


+ 1 - 1
src/Mesh/babylon.transformNode.ts

@@ -306,7 +306,7 @@ module BABYLON {
          * @param postMultiplyPivotMatrix defines if the pivot matrix must be cancelled in the world matrix. When this parameter is set to true (default), the inverse of the pivot matrix is also applied at the end to cancel the transformation effect
          * @returns the current TransformNode
         */
-        public setPivotMatrix(matrix: Readonly<Matrix>, postMultiplyPivotMatrix = true): TransformNode {
+        public setPivotMatrix(matrix: DeepImmutable<Matrix>, postMultiplyPivotMatrix = true): TransformNode {
             this._pivotMatrix.copyFrom(matrix);
             this._cache.pivotMatrixUpdated = true;
             this._postMultiplyPivotMatrix = postMultiplyPivotMatrix;

+ 33 - 0
src/babylon.types.ts

@@ -26,4 +26,37 @@ module BABYLON {
      * Alias for types that can be used by a Buffer or VertexBuffer.
      */
     export type DataArray = number[] | ArrayBuffer | ArrayBufferView;
+
+    /**
+     * Alias type for primitive types
+     * @ignorenaming
+     */
+    type Primitive = undefined | null | boolean | string | number | Function;
+
+    /**
+     * Type modifier to make all the properties of an object Readonly
+     */
+    export type Immutable<T> = T extends Primitive
+      ? T
+      : T extends Array<infer U>
+        ? ReadonlyArray<U>
+        : /* T extends Map<infer K, infer V> ? ReadonlyMap<K, V> : // es2015+ only */
+          DeepImmutable<T>;
+
+    /**
+     * Type modifier to make all the properties of an object Readonly recursively
+     */
+    export type DeepImmutable<T> = T extends Primitive
+      ? T
+      : T extends Array<infer U>
+        ? DeepImmutableArray<U>
+        : /* T extends Map<infer K, infer V> ? DeepImmutableMap<K, V> : // es2015+ only */
+          DeepImmutableObject<T>;
+
+    /** @hidden */
+    interface DeepImmutableArray<T> extends ReadonlyArray<DeepImmutable<T>> {}
+    /** @hidden */
+    /* interface DeepImmutableMap<K, V> extends ReadonlyMap<DeepImmutable<K>, DeepImmutable<V>> {} // es2015+ only */
+    /** @hidden */
+    type DeepImmutableObject<T> = { readonly [K in keyof T]: DeepImmutable<T[K]> };
 }