Browse Source

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js into shader-if-expression

Popov72 5 năm trước cách đây
mục cha
commit
c83ad761ad
36 tập tin đã thay đổi với 393 bổ sung150 xóa
  1. 11 6
      dist/preview release/babylon.d.ts
  2. 1 1
      dist/preview release/babylon.js
  3. 55 50
      dist/preview release/babylon.max.js
  4. 1 1
      dist/preview release/babylon.max.js.map
  5. 22 12
      dist/preview release/babylon.module.d.ts
  6. 11 6
      dist/preview release/documentation.d.ts
  7. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.js
  8. 3 2
      dist/preview release/inspector/babylon.inspector.bundle.max.js
  9. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.max.js.map
  10. 5 0
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  11. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.js.map
  12. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  13. 5 0
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  14. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.js.map
  15. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  16. 5 0
      dist/preview release/loaders/babylon.glTFFileLoader.js
  17. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.js.map
  18. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  19. 5 0
      dist/preview release/loaders/babylonjs.loaders.js
  20. 1 1
      dist/preview release/loaders/babylonjs.loaders.js.map
  21. 2 2
      dist/preview release/loaders/babylonjs.loaders.min.js
  22. 2 0
      dist/preview release/nodeEditor/babylon.nodeEditor.d.ts
  23. 7 7
      dist/preview release/nodeEditor/babylon.nodeEditor.js
  24. 74 5
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js
  25. 1 1
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map
  26. 4 0
      dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts
  27. 22 12
      dist/preview release/viewer/babylon.module.d.ts
  28. 7 7
      dist/preview release/viewer/babylon.viewer.js
  29. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  30. 3 0
      dist/preview release/what's new.md
  31. 4 2
      inspector/src/components/actionTabs/tabs/propertyGrids/particleSystems/particleSystemPropertyGridComponent.tsx
  32. 5 0
      loaders/src/glTF/glTFFileLoader.ts
  33. 96 7
      nodeEditor/src/components/propertyTab/propertyTabComponent.tsx
  34. 13 2
      src/Materials/Node/nodeMaterial.ts
  35. 15 13
      src/Materials/Textures/Packer/packer.ts
  36. 3 3
      src/Misc/assetsManager.ts

+ 11 - 6
dist/preview release/babylon.d.ts

@@ -57445,6 +57445,10 @@ declare module BABYLON {
         /** Get the inspector from bundle or global */
         private _getGlobalNodeMaterialEditor;
         /**
+         * Snippet ID if the material was created from the snippet server
+         */
+        snippetId: string;
+        /**
          * Gets or sets data used by visual editor
          * @see https://nme.babylonjs.com
          */
@@ -57703,9 +57707,10 @@ declare module BABYLON {
          * @param snippetId defines the snippet to load
          * @param scene defines the hosting scene
          * @param rootUrl defines the root URL to use to load textures and relative dependencies
+         * @param nodeMaterial defines a node material to update (instead of creating a new one)
          * @returns a promise that will resolve to the new node material
          */
-        static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl?: string): Promise<NodeMaterial>;
+        static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl?: string, nodeMaterial?: NodeMaterial): Promise<NodeMaterial>;
         /**
          * Creates a new node material set to default basic configuration
          * @param name defines the name of the material
@@ -67984,9 +67989,9 @@ declare module BABYLON {
          */
         noMipmap?: boolean | undefined;
         /**
-         * Defines if texture must be inverted on Y axis (default is false)
+         * Defines if texture must be inverted on Y axis (default is true)
          */
-        invertY?: boolean | undefined;
+        invertY: boolean;
         /**
          * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
@@ -68008,7 +68013,7 @@ declare module BABYLON {
          * @param name defines the name of the task
          * @param url defines the location of the file to load
          * @param noMipmap defines if mipmap should not be generated (default is false)
-         * @param invertY defines if texture must be inverted on Y axis (default is false)
+         * @param invertY defines if texture must be inverted on Y axis (default is true)
          * @param samplingMode defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
         constructor(
@@ -68025,9 +68030,9 @@ declare module BABYLON {
          */
         noMipmap?: boolean | undefined, 
         /**
-         * Defines if texture must be inverted on Y axis (default is false)
+         * Defines if texture must be inverted on Y axis (default is true)
          */
-        invertY?: boolean | undefined, 
+        invertY?: boolean, 
         /**
          * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/babylon.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 55 - 50
dist/preview release/babylon.max.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/babylon.max.js.map


+ 22 - 12
dist/preview release/babylon.module.d.ts

@@ -60107,6 +60107,10 @@ declare module "babylonjs/Materials/Node/nodeMaterial" {
         /** Get the inspector from bundle or global */
         private _getGlobalNodeMaterialEditor;
         /**
+         * Snippet ID if the material was created from the snippet server
+         */
+        snippetId: string;
+        /**
          * Gets or sets data used by visual editor
          * @see https://nme.babylonjs.com
          */
@@ -60365,9 +60369,10 @@ declare module "babylonjs/Materials/Node/nodeMaterial" {
          * @param snippetId defines the snippet to load
          * @param scene defines the hosting scene
          * @param rootUrl defines the root URL to use to load textures and relative dependencies
+         * @param nodeMaterial defines a node material to update (instead of creating a new one)
          * @returns a promise that will resolve to the new node material
          */
-        static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl?: string): Promise<NodeMaterial>;
+        static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl?: string, nodeMaterial?: NodeMaterial): Promise<NodeMaterial>;
         /**
          * Creates a new node material set to default basic configuration
          * @param name defines the name of the material
@@ -71651,9 +71656,9 @@ declare module "babylonjs/Misc/assetsManager" {
          */
         noMipmap?: boolean | undefined;
         /**
-         * Defines if texture must be inverted on Y axis (default is false)
+         * Defines if texture must be inverted on Y axis (default is true)
          */
-        invertY?: boolean | undefined;
+        invertY: boolean;
         /**
          * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
@@ -71675,7 +71680,7 @@ declare module "babylonjs/Misc/assetsManager" {
          * @param name defines the name of the task
          * @param url defines the location of the file to load
          * @param noMipmap defines if mipmap should not be generated (default is false)
-         * @param invertY defines if texture must be inverted on Y axis (default is false)
+         * @param invertY defines if texture must be inverted on Y axis (default is true)
          * @param samplingMode defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
         constructor(
@@ -71692,9 +71697,9 @@ declare module "babylonjs/Misc/assetsManager" {
          */
         noMipmap?: boolean | undefined, 
         /**
-         * Defines if texture must be inverted on Y axis (default is false)
+         * Defines if texture must be inverted on Y axis (default is true)
          */
-        invertY?: boolean | undefined, 
+        invertY?: boolean, 
         /**
          * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
@@ -131562,6 +131567,10 @@ declare module BABYLON {
         /** Get the inspector from bundle or global */
         private _getGlobalNodeMaterialEditor;
         /**
+         * Snippet ID if the material was created from the snippet server
+         */
+        snippetId: string;
+        /**
          * Gets or sets data used by visual editor
          * @see https://nme.babylonjs.com
          */
@@ -131820,9 +131829,10 @@ declare module BABYLON {
          * @param snippetId defines the snippet to load
          * @param scene defines the hosting scene
          * @param rootUrl defines the root URL to use to load textures and relative dependencies
+         * @param nodeMaterial defines a node material to update (instead of creating a new one)
          * @returns a promise that will resolve to the new node material
          */
-        static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl?: string): Promise<NodeMaterial>;
+        static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl?: string, nodeMaterial?: NodeMaterial): Promise<NodeMaterial>;
         /**
          * Creates a new node material set to default basic configuration
          * @param name defines the name of the material
@@ -142101,9 +142111,9 @@ declare module BABYLON {
          */
         noMipmap?: boolean | undefined;
         /**
-         * Defines if texture must be inverted on Y axis (default is false)
+         * Defines if texture must be inverted on Y axis (default is true)
          */
-        invertY?: boolean | undefined;
+        invertY: boolean;
         /**
          * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
@@ -142125,7 +142135,7 @@ declare module BABYLON {
          * @param name defines the name of the task
          * @param url defines the location of the file to load
          * @param noMipmap defines if mipmap should not be generated (default is false)
-         * @param invertY defines if texture must be inverted on Y axis (default is false)
+         * @param invertY defines if texture must be inverted on Y axis (default is true)
          * @param samplingMode defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
         constructor(
@@ -142142,9 +142152,9 @@ declare module BABYLON {
          */
         noMipmap?: boolean | undefined, 
         /**
-         * Defines if texture must be inverted on Y axis (default is false)
+         * Defines if texture must be inverted on Y axis (default is true)
          */
-        invertY?: boolean | undefined, 
+        invertY?: boolean, 
         /**
          * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */

+ 11 - 6
dist/preview release/documentation.d.ts

@@ -57445,6 +57445,10 @@ declare module BABYLON {
         /** Get the inspector from bundle or global */
         private _getGlobalNodeMaterialEditor;
         /**
+         * Snippet ID if the material was created from the snippet server
+         */
+        snippetId: string;
+        /**
          * Gets or sets data used by visual editor
          * @see https://nme.babylonjs.com
          */
@@ -57703,9 +57707,10 @@ declare module BABYLON {
          * @param snippetId defines the snippet to load
          * @param scene defines the hosting scene
          * @param rootUrl defines the root URL to use to load textures and relative dependencies
+         * @param nodeMaterial defines a node material to update (instead of creating a new one)
          * @returns a promise that will resolve to the new node material
          */
-        static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl?: string): Promise<NodeMaterial>;
+        static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl?: string, nodeMaterial?: NodeMaterial): Promise<NodeMaterial>;
         /**
          * Creates a new node material set to default basic configuration
          * @param name defines the name of the material
@@ -67984,9 +67989,9 @@ declare module BABYLON {
          */
         noMipmap?: boolean | undefined;
         /**
-         * Defines if texture must be inverted on Y axis (default is false)
+         * Defines if texture must be inverted on Y axis (default is true)
          */
-        invertY?: boolean | undefined;
+        invertY: boolean;
         /**
          * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
@@ -68008,7 +68013,7 @@ declare module BABYLON {
          * @param name defines the name of the task
          * @param url defines the location of the file to load
          * @param noMipmap defines if mipmap should not be generated (default is false)
-         * @param invertY defines if texture must be inverted on Y axis (default is false)
+         * @param invertY defines if texture must be inverted on Y axis (default is true)
          * @param samplingMode defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
         constructor(
@@ -68025,9 +68030,9 @@ declare module BABYLON {
          */
         noMipmap?: boolean | undefined, 
         /**
-         * Defines if texture must be inverted on Y axis (default is false)
+         * Defines if texture must be inverted on Y axis (default is true)
          */
-        invertY?: boolean | undefined, 
+        invertY?: boolean, 
         /**
          * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js


+ 3 - 2
dist/preview release/inspector/babylon.inspector.bundle.max.js

@@ -47621,7 +47621,7 @@ var ParticleSystemPropertyGridComponent = /** @class */ (function (_super) {
                         navigator.clipboard.writeText(system.snippetId);
                     }
                     var windowAsAny = window;
-                    if (windowAsAny.Playground) {
+                    if (windowAsAny.Playground && oldId) {
                         windowAsAny.Playground.onRequestCodeChangeObservable.notifyObservers({
                             regex: new RegExp(oldId, "g"),
                             replace: system.snippetId
@@ -47697,7 +47697,8 @@ var ParticleSystemPropertyGridComponent = /** @class */ (function (_super) {
                     } })),
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lineContainerComponent__WEBPACK_IMPORTED_MODULE_2__["LineContainerComponent"], { globalState: this.props.globalState, title: "FILE" },
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_fileButtonLineComponent__WEBPACK_IMPORTED_MODULE_22__["FileButtonLineComponent"], { label: "Load", onClick: function (file) { return _this.loadFromFile(file); }, accept: ".json" }),
-                react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_buttonLineComponent__WEBPACK_IMPORTED_MODULE_6__["ButtonLineComponent"], { label: "Save", onClick: function () { return _this.saveToFile(); } }),
+                react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_buttonLineComponent__WEBPACK_IMPORTED_MODULE_6__["ButtonLineComponent"], { label: "Save", onClick: function () { return _this.saveToFile(); } })),
+            react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lineContainerComponent__WEBPACK_IMPORTED_MODULE_2__["LineContainerComponent"], { globalState: this.props.globalState, title: "SNIPPET" },
                 system.snippetId &&
                     react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_textLineComponent__WEBPACK_IMPORTED_MODULE_3__["TextLineComponent"], { label: "Snippet ID", value: system.snippetId }),
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_buttonLineComponent__WEBPACK_IMPORTED_MODULE_6__["ButtonLineComponent"], { label: "Load from snippet server", onClick: function () { return _this.loadFromSnippet(); } }),

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.max.js.map


+ 5 - 0
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -3206,6 +3206,10 @@ var GLTFFileLoader = /** @class */ (function () {
             _this.onTextureLoadedObservable.add(function (texture) {
                 textures.push(texture);
             });
+            var cameras = [];
+            _this.onCameraLoadedObservable.add(function (camera) {
+                cameras.push(camera);
+            });
             return _this._loader.importMeshAsync(null, scene, true, data, rootUrl, onProgress, fileName).then(function (result) {
                 var container = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__["AssetContainer"](scene);
                 Array.prototype.push.apply(container.meshes, result.meshes);
@@ -3216,6 +3220,7 @@ var GLTFFileLoader = /** @class */ (function () {
                 Array.prototype.push.apply(container.textures, textures);
                 Array.prototype.push.apply(container.lights, result.lights);
                 Array.prototype.push.apply(container.transformNodes, result.transformNodes);
+                Array.prototype.push.apply(container.cameras, cameras);
                 return container;
             });
         });

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.js.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 5 - 0
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -4676,6 +4676,10 @@ var GLTFFileLoader = /** @class */ (function () {
             _this.onTextureLoadedObservable.add(function (texture) {
                 textures.push(texture);
             });
+            var cameras = [];
+            _this.onCameraLoadedObservable.add(function (camera) {
+                cameras.push(camera);
+            });
             return _this._loader.importMeshAsync(null, scene, true, data, rootUrl, onProgress, fileName).then(function (result) {
                 var container = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__["AssetContainer"](scene);
                 Array.prototype.push.apply(container.meshes, result.meshes);
@@ -4686,6 +4690,7 @@ var GLTFFileLoader = /** @class */ (function () {
                 Array.prototype.push.apply(container.textures, textures);
                 Array.prototype.push.apply(container.lights, result.lights);
                 Array.prototype.push.apply(container.transformNodes, result.transformNodes);
+                Array.prototype.push.apply(container.cameras, cameras);
                 return container;
             });
         });

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.js.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 5 - 0
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -7256,6 +7256,10 @@ var GLTFFileLoader = /** @class */ (function () {
             _this.onTextureLoadedObservable.add(function (texture) {
                 textures.push(texture);
             });
+            var cameras = [];
+            _this.onCameraLoadedObservable.add(function (camera) {
+                cameras.push(camera);
+            });
             return _this._loader.importMeshAsync(null, scene, true, data, rootUrl, onProgress, fileName).then(function (result) {
                 var container = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__["AssetContainer"](scene);
                 Array.prototype.push.apply(container.meshes, result.meshes);
@@ -7266,6 +7270,7 @@ var GLTFFileLoader = /** @class */ (function () {
                 Array.prototype.push.apply(container.textures, textures);
                 Array.prototype.push.apply(container.lights, result.lights);
                 Array.prototype.push.apply(container.transformNodes, result.transformNodes);
+                Array.prototype.push.apply(container.cameras, cameras);
                 return container;
             });
         });

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.js.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 5 - 0
dist/preview release/loaders/babylonjs.loaders.js

@@ -8636,6 +8636,10 @@ var GLTFFileLoader = /** @class */ (function () {
             _this.onTextureLoadedObservable.add(function (texture) {
                 textures.push(texture);
             });
+            var cameras = [];
+            _this.onCameraLoadedObservable.add(function (camera) {
+                cameras.push(camera);
+            });
             return _this._loader.importMeshAsync(null, scene, true, data, rootUrl, onProgress, fileName).then(function (result) {
                 var container = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__["AssetContainer"](scene);
                 Array.prototype.push.apply(container.meshes, result.meshes);
@@ -8646,6 +8650,7 @@ var GLTFFileLoader = /** @class */ (function () {
                 Array.prototype.push.apply(container.textures, textures);
                 Array.prototype.push.apply(container.lights, result.lights);
                 Array.prototype.push.apply(container.transformNodes, result.transformNodes);
+                Array.prototype.push.apply(container.cameras, cameras);
                 return container;
             });
         });

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.js.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 2 - 2
dist/preview release/loaders/babylonjs.loaders.min.js


+ 2 - 0
dist/preview release/nodeEditor/babylon.nodeEditor.d.ts

@@ -1241,6 +1241,8 @@ declare module NODEEDITOR {
         load(file: File): void;
         save(): void;
         customSave(): void;
+        saveToSnippetServer(): void;
+        loadFromSnippet(): void;
         render(): JSX.Element;
     }
 }

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 7 - 7
dist/preview release/nodeEditor/babylon.nodeEditor.js


+ 74 - 5
dist/preview release/nodeEditor/babylon.nodeEditor.max.js

@@ -52884,6 +52884,7 @@ __webpack_require__.r(__webpack_exports__);
 
 
 
+
 __webpack_require__(/*! ./propertyTab.scss */ "./components/propertyTab/propertyTab.scss");
 var PropertyTabComponent = /** @class */ (function (_super) {
     Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"])(PropertyTabComponent, _super);
@@ -52968,6 +52969,66 @@ var PropertyTabComponent = /** @class */ (function (_super) {
             _this.props.globalState.onLogRequiredObservable.notifyObservers({ message: err, isError: true });
         });
     };
+    PropertyTabComponent.prototype.saveToSnippetServer = function () {
+        var _this = this;
+        var material = this.props.globalState.nodeMaterial;
+        var xmlHttp = new XMLHttpRequest();
+        var json = _serializationTools__WEBPACK_IMPORTED_MODULE_7__["SerializationTools"].Serialize(material, this.props.globalState);
+        xmlHttp.onreadystatechange = function () {
+            if (xmlHttp.readyState == 4) {
+                if (xmlHttp.status == 200) {
+                    var snippet = JSON.parse(xmlHttp.responseText);
+                    var oldId = material.snippetId;
+                    material.snippetId = snippet.id;
+                    if (snippet.version && snippet.version != "0") {
+                        material.snippetId += "#" + snippet.version;
+                    }
+                    _this.forceUpdate();
+                    if (navigator.clipboard) {
+                        navigator.clipboard.writeText(material.snippetId);
+                    }
+                    var windowAsAny = window;
+                    if (windowAsAny.Playground && oldId) {
+                        windowAsAny.Playground.onRequestCodeChangeObservable.notifyObservers({
+                            regex: new RegExp(oldId, "g"),
+                            replace: material.snippetId
+                        });
+                    }
+                    alert("NodeMaterial saved with ID: " + material.snippetId + " (please note that the id was also saved to your clipboard)");
+                }
+                else {
+                    alert("Unable to save your node material. It may be too large (" + (dataToSend.payload.length / 1024).toFixed(2) + " KB) because of embedded textures. Please reduce texture sizes or point to a specific url instead of embedding them and try again.");
+                }
+            }
+        };
+        xmlHttp.open("POST", babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_6__["NodeMaterial"].SnippetUrl + (material.snippetId ? "/" + material.snippetId : ""), true);
+        xmlHttp.setRequestHeader("Content-Type", "application/json");
+        var dataToSend = {
+            payload: JSON.stringify({
+                nodeMaterial: json
+            }),
+            name: "",
+            description: "",
+            tags: ""
+        };
+        xmlHttp.send(JSON.stringify(dataToSend));
+    };
+    PropertyTabComponent.prototype.loadFromSnippet = function () {
+        var _this = this;
+        var material = this.props.globalState.nodeMaterial;
+        var scene = material.getScene();
+        var snippedID = window.prompt("Please enter the snippet ID to use");
+        if (!snippedID) {
+            return;
+        }
+        this.props.globalState.onSelectionChangedObservable.notifyObservers(null);
+        babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_6__["NodeMaterial"].ParseFromSnippetAsync(snippedID, scene, "", material).then(function () {
+            material.build();
+            _this.props.globalState.onResetRequiredObservable.notifyObservers();
+        }).catch(function (err) {
+            alert("Unable to load your node material: " + err);
+        });
+    };
     PropertyTabComponent.prototype.render = function () {
         var _this = this;
         if (this.state.currentNode) {
@@ -53021,16 +53082,24 @@ var PropertyTabComponent = /** @class */ (function (_super) {
                     react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_buttonLineComponent__WEBPACK_IMPORTED_MODULE_2__["ButtonLineComponent"], { label: "Save", onClick: function () {
                             _this.save();
                         } }),
-                    this.props.globalState.customSave &&
-                        react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_buttonLineComponent__WEBPACK_IMPORTED_MODULE_2__["ButtonLineComponent"], { label: this.props.globalState.customSave.label, onClick: function () {
-                                _this.customSave();
-                            } }),
                     react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_buttonLineComponent__WEBPACK_IMPORTED_MODULE_2__["ButtonLineComponent"], { label: "Generate code", onClick: function () {
                             _stringTools__WEBPACK_IMPORTED_MODULE_4__["StringTools"].DownloadAsFile(_this.props.globalState.hostDocument, _this.props.globalState.nodeMaterial.generateCode(), "code.txt");
                         } }),
                     react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_buttonLineComponent__WEBPACK_IMPORTED_MODULE_2__["ButtonLineComponent"], { label: "Export shaders", onClick: function () {
                             _stringTools__WEBPACK_IMPORTED_MODULE_4__["StringTools"].DownloadAsFile(_this.props.globalState.hostDocument, _this.props.globalState.nodeMaterial.compiledShaders, "shaders.txt");
-                        } })),
+                        } }),
+                    this.props.globalState.customSave &&
+                        react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_buttonLineComponent__WEBPACK_IMPORTED_MODULE_2__["ButtonLineComponent"], { label: this.props.globalState.customSave.label, onClick: function () {
+                                _this.customSave();
+                            } })),
+                !this.props.globalState.customSave &&
+                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_lineContainerComponent__WEBPACK_IMPORTED_MODULE_3__["LineContainerComponent"], { title: "SNIPPET" },
+                        this.props.globalState.nodeMaterial.snippetId &&
+                            react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_textLineComponent__WEBPACK_IMPORTED_MODULE_12__["TextLineComponent"], { label: "Snippet ID", value: this.props.globalState.nodeMaterial.snippetId }),
+                        react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_buttonLineComponent__WEBPACK_IMPORTED_MODULE_2__["ButtonLineComponent"], { label: "Load from snippet server", onClick: function () { return _this.loadFromSnippet(); } }),
+                        react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_buttonLineComponent__WEBPACK_IMPORTED_MODULE_2__["ButtonLineComponent"], { label: "Save to snippet server", onClick: function () {
+                                _this.saveToSnippetServer();
+                            } })),
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_lineContainerComponent__WEBPACK_IMPORTED_MODULE_3__["LineContainerComponent"], { title: "INPUTS" }, this.props.globalState.nodeMaterial.getInputBlocks().map(function (ib) {
                     if (!ib.isUniform || ib.isSystemValue || !ib.name) {
                         return null;

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map


+ 4 - 0
dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts

@@ -1499,6 +1499,8 @@ declare module "babylonjs-node-editor/components/propertyTab/propertyTabComponen
         load(file: File): void;
         save(): void;
         customSave(): void;
+        saveToSnippetServer(): void;
+        loadFromSnippet(): void;
         render(): JSX.Element;
     }
 }
@@ -2951,6 +2953,8 @@ declare module NODEEDITOR {
         load(file: File): void;
         save(): void;
         customSave(): void;
+        saveToSnippetServer(): void;
+        loadFromSnippet(): void;
         render(): JSX.Element;
     }
 }

+ 22 - 12
dist/preview release/viewer/babylon.module.d.ts

@@ -60107,6 +60107,10 @@ declare module "babylonjs/Materials/Node/nodeMaterial" {
         /** Get the inspector from bundle or global */
         private _getGlobalNodeMaterialEditor;
         /**
+         * Snippet ID if the material was created from the snippet server
+         */
+        snippetId: string;
+        /**
          * Gets or sets data used by visual editor
          * @see https://nme.babylonjs.com
          */
@@ -60365,9 +60369,10 @@ declare module "babylonjs/Materials/Node/nodeMaterial" {
          * @param snippetId defines the snippet to load
          * @param scene defines the hosting scene
          * @param rootUrl defines the root URL to use to load textures and relative dependencies
+         * @param nodeMaterial defines a node material to update (instead of creating a new one)
          * @returns a promise that will resolve to the new node material
          */
-        static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl?: string): Promise<NodeMaterial>;
+        static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl?: string, nodeMaterial?: NodeMaterial): Promise<NodeMaterial>;
         /**
          * Creates a new node material set to default basic configuration
          * @param name defines the name of the material
@@ -71651,9 +71656,9 @@ declare module "babylonjs/Misc/assetsManager" {
          */
         noMipmap?: boolean | undefined;
         /**
-         * Defines if texture must be inverted on Y axis (default is false)
+         * Defines if texture must be inverted on Y axis (default is true)
          */
-        invertY?: boolean | undefined;
+        invertY: boolean;
         /**
          * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
@@ -71675,7 +71680,7 @@ declare module "babylonjs/Misc/assetsManager" {
          * @param name defines the name of the task
          * @param url defines the location of the file to load
          * @param noMipmap defines if mipmap should not be generated (default is false)
-         * @param invertY defines if texture must be inverted on Y axis (default is false)
+         * @param invertY defines if texture must be inverted on Y axis (default is true)
          * @param samplingMode defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
         constructor(
@@ -71692,9 +71697,9 @@ declare module "babylonjs/Misc/assetsManager" {
          */
         noMipmap?: boolean | undefined, 
         /**
-         * Defines if texture must be inverted on Y axis (default is false)
+         * Defines if texture must be inverted on Y axis (default is true)
          */
-        invertY?: boolean | undefined, 
+        invertY?: boolean, 
         /**
          * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
@@ -131562,6 +131567,10 @@ declare module BABYLON {
         /** Get the inspector from bundle or global */
         private _getGlobalNodeMaterialEditor;
         /**
+         * Snippet ID if the material was created from the snippet server
+         */
+        snippetId: string;
+        /**
          * Gets or sets data used by visual editor
          * @see https://nme.babylonjs.com
          */
@@ -131820,9 +131829,10 @@ declare module BABYLON {
          * @param snippetId defines the snippet to load
          * @param scene defines the hosting scene
          * @param rootUrl defines the root URL to use to load textures and relative dependencies
+         * @param nodeMaterial defines a node material to update (instead of creating a new one)
          * @returns a promise that will resolve to the new node material
          */
-        static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl?: string): Promise<NodeMaterial>;
+        static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl?: string, nodeMaterial?: NodeMaterial): Promise<NodeMaterial>;
         /**
          * Creates a new node material set to default basic configuration
          * @param name defines the name of the material
@@ -142101,9 +142111,9 @@ declare module BABYLON {
          */
         noMipmap?: boolean | undefined;
         /**
-         * Defines if texture must be inverted on Y axis (default is false)
+         * Defines if texture must be inverted on Y axis (default is true)
          */
-        invertY?: boolean | undefined;
+        invertY: boolean;
         /**
          * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
@@ -142125,7 +142135,7 @@ declare module BABYLON {
          * @param name defines the name of the task
          * @param url defines the location of the file to load
          * @param noMipmap defines if mipmap should not be generated (default is false)
-         * @param invertY defines if texture must be inverted on Y axis (default is false)
+         * @param invertY defines if texture must be inverted on Y axis (default is true)
          * @param samplingMode defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */
         constructor(
@@ -142142,9 +142152,9 @@ declare module BABYLON {
          */
         noMipmap?: boolean | undefined, 
         /**
-         * Defines if texture must be inverted on Y axis (default is false)
+         * Defines if texture must be inverted on Y axis (default is true)
          */
-        invertY?: boolean | undefined, 
+        invertY?: boolean, 
         /**
          * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 7 - 7
dist/preview release/viewer/babylon.viewer.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


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

@@ -44,6 +44,7 @@
 ### Loaders
 
 - Added support for glTF mesh instancing extension ([#7521](https://github.com/BabylonJS/Babylon.js/issues/7521)) ([drigax](https://github.com/Drigax))
+- Get the list of cameras retrieved from a gLTF file when loaded through the asset container ([Popov72](https://github.com/Popov72))
 
 ### Navigation
 
@@ -92,5 +93,7 @@
 - Fix bug in PBR when translucency is enabled and an irradiance texture is provided ([Popov72](https://github.com/Popov72)
 - Fix bug in PBR with translucency when irradiance texture is 2D ([Popov72](https://github.com/Popov72)
 - Fix bug in PBR when specific combinations of parameters are used ([Popov72](https://github.com/Popov72)
+- Fix texture being inverted on the Y axis by default when using TextureAsset or AssetManager ([broederj](https://github.com/broederj))
+- Fix `TexturePacker` cross-origin image requests, fix falsy default options ([ludevik](https://github.com/ludevik))
 
 ## Breaking changes

+ 4 - 2
inspector/src/components/actionTabs/tabs/propertyGrids/particleSystems/particleSystemPropertyGridComponent.tsx

@@ -221,7 +221,7 @@ export class ParticleSystemPropertyGridComponent extends React.Component<IPartic
 
                     let windowAsAny = window as any;
 
-                    if (windowAsAny.Playground) {
+                    if (windowAsAny.Playground && oldId) {
                         windowAsAny.Playground.onRequestCodeChangeObservable.notifyObservers({
                             regex: new RegExp(oldId, "g"),
                             replace: system.snippetId
@@ -315,13 +315,15 @@ export class ParticleSystemPropertyGridComponent extends React.Component<IPartic
                 <LineContainerComponent globalState={this.props.globalState} title="FILE">
                 <FileButtonLineComponent label="Load" onClick={(file) => this.loadFromFile(file)} accept=".json" />
                     <ButtonLineComponent label="Save" onClick={() => this.saveToFile()} />
+                </LineContainerComponent>
+                <LineContainerComponent globalState={this.props.globalState} title="SNIPPET">
                     {
                         system.snippetId &&
                         <TextLineComponent label="Snippet ID" value={system.snippetId} />
                     }
                     <ButtonLineComponent label="Load from snippet server" onClick={() => this.loadFromSnippet()} />
                     <ButtonLineComponent label="Save to snippet server" onClick={() => this.saveToSnippet()} />
-                </LineContainerComponent>
+                </LineContainerComponent>                
                 <LineContainerComponent globalState={this.props.globalState} title="EMITTER">
                 <OptionsLineComponent 
                         label="Emitter" 

+ 5 - 0
loaders/src/glTF/glTFFileLoader.ts

@@ -597,6 +597,10 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
             this.onTextureLoadedObservable.add((texture) => {
                 textures.push(texture);
             });
+            const cameras: Array<Camera> = [];
+            this.onCameraLoadedObservable.add((camera) => {
+                cameras.push(camera);
+            });
 
             return this._loader.importMeshAsync(null, scene, true, data, rootUrl, onProgress, fileName).then((result) => {
                 const container = new AssetContainer(scene);
@@ -608,6 +612,7 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
                 Array.prototype.push.apply(container.textures, textures);
                 Array.prototype.push.apply(container.lights, result.lights);
                 Array.prototype.push.apply(container.transformNodes, result.transformNodes);
+                Array.prototype.push.apply(container.cameras, cameras);
                 return container;
             });
         });

+ 96 - 7
nodeEditor/src/components/propertyTab/propertyTabComponent.tsx

@@ -27,6 +27,7 @@ import { Vector3LineComponent } from '../../sharedComponents/vector3LineComponen
 import { Vector4LineComponent } from '../../sharedComponents/vector4LineComponent';
 import { Observer } from 'babylonjs/Misc/observable';
 import { NodePort } from '../../diagram/nodePort';
+import { NodeMaterial } from 'babylonjs/Materials/Node/nodeMaterial';
 require("./propertyTab.scss");
 
 interface IPropertyTabComponentProps {
@@ -154,6 +155,80 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
         });
     }
 
+    saveToSnippetServer() {
+        const material = this.props.globalState.nodeMaterial;
+        const xmlHttp = new XMLHttpRequest();
+        
+        let json = SerializationTools.Serialize(material, this.props.globalState);
+
+        xmlHttp.onreadystatechange = () => {
+            if (xmlHttp.readyState == 4) {
+                if (xmlHttp.status == 200) {
+                    var snippet = JSON.parse(xmlHttp.responseText);
+                    const oldId = material.snippetId;
+                    material.snippetId = snippet.id;
+                    if (snippet.version && snippet.version != "0") {
+                        material.snippetId += "#" + snippet.version;
+                    }
+
+                    this.forceUpdate();
+                    if (navigator.clipboard) {
+                        navigator.clipboard.writeText(material.snippetId);
+                    }
+
+                    let windowAsAny = window as any;
+
+                    if (windowAsAny.Playground && oldId) {
+                        windowAsAny.Playground.onRequestCodeChangeObservable.notifyObservers({
+                            regex: new RegExp(oldId, "g"),
+                            replace: material.snippetId
+                        });
+                    }
+
+                    alert("NodeMaterial saved with ID: " + material.snippetId + " (please note that the id was also saved to your clipboard)");
+                               
+                }
+                else {
+                    alert(`Unable to save your node material. It may be too large (${(dataToSend.payload.length / 1024).toFixed(2)} KB) because of embedded textures. Please reduce texture sizes or point to a specific url instead of embedding them and try again.`);
+                }
+            }
+        }
+
+        xmlHttp.open("POST", NodeMaterial.SnippetUrl + (material.snippetId ? "/" + material.snippetId : ""), true);
+        xmlHttp.setRequestHeader("Content-Type", "application/json");
+
+        var dataToSend = {
+            payload : JSON.stringify({
+                nodeMaterial: json
+            }),
+            name: "",
+            description: "",
+            tags: ""
+        };
+
+        xmlHttp.send(JSON.stringify(dataToSend));
+    }
+
+    loadFromSnippet() {
+        const material = this.props.globalState.nodeMaterial;
+        const scene = material.getScene();
+
+        let snippedID = window.prompt("Please enter the snippet ID to use");
+
+        if (!snippedID) {
+            return;
+        }
+        
+        this.props.globalState.onSelectionChangedObservable.notifyObservers(null);
+
+        NodeMaterial.ParseFromSnippetAsync(snippedID, scene, "", material).then(() => {
+            material.build();
+            this.props.globalState.onResetRequiredObservable.notifyObservers();
+        }).catch(err => {
+            alert("Unable to load your node material: " + err);
+        });
+    }    
+
     render() {
         if (this.state.currentNode) {
             return (
@@ -237,19 +312,33 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
                         <ButtonLineComponent label="Save" onClick={() => {
                             this.save();
                         }} />
-                        {
-                            this.props.globalState.customSave && 
-                            <ButtonLineComponent label={this.props.globalState.customSave!.label} onClick={() => {
-                                this.customSave();
-                            }} />
-                        }
                         <ButtonLineComponent label="Generate code" onClick={() => {
                             StringTools.DownloadAsFile(this.props.globalState.hostDocument, this.props.globalState.nodeMaterial!.generateCode(), "code.txt");
                         }} />
                         <ButtonLineComponent label="Export shaders" onClick={() => {
                             StringTools.DownloadAsFile(this.props.globalState.hostDocument, this.props.globalState.nodeMaterial!.compiledShaders, "shaders.txt");
                         }} />
-                    </LineContainerComponent>                    
+                        {
+                            this.props.globalState.customSave && 
+                            <ButtonLineComponent label={this.props.globalState.customSave!.label} onClick={() => {
+                                this.customSave();
+                            }} />
+                        }                        
+
+                    </LineContainerComponent>                            
+                    {
+                        !this.props.globalState.customSave &&                           
+                        <LineContainerComponent title="SNIPPET"> 
+                            {
+                                this.props.globalState.nodeMaterial!.snippetId &&
+                                <TextLineComponent label="Snippet ID" value={this.props.globalState.nodeMaterial!.snippetId} />
+                            }                                
+                            <ButtonLineComponent label="Load from snippet server" onClick={() => this.loadFromSnippet()} />
+                            <ButtonLineComponent label="Save to snippet server" onClick={() => {
+                                this.saveToSnippetServer();
+                            }} />
+                        </LineContainerComponent>  
+                    }                
                     <LineContainerComponent title="INPUTS">   
                     {
                         this.props.globalState.nodeMaterial.getInputBlocks().map(ib => {

+ 13 - 2
src/Materials/Node/nodeMaterial.ts

@@ -143,6 +143,11 @@ export class NodeMaterial extends PushMaterial {
     }
 
     /**
+     * Snippet ID if the material was created from the snippet server
+     */
+    public snippetId: string;
+
+    /**
      * Gets or sets data used by visual editor
      * @see https://nme.babylonjs.com
      */
@@ -1337,9 +1342,10 @@ export class NodeMaterial extends PushMaterial {
      * @param snippetId defines the snippet to load
      * @param scene defines the hosting scene
      * @param rootUrl defines the root URL to use to load textures and relative dependencies
+     * @param nodeMaterial defines a node material to update (instead of creating a new one)
      * @returns a promise that will resolve to the new node material
      */
-    public static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl: string = ""): Promise<NodeMaterial> {
+    public static ParseFromSnippetAsync(snippetId: string, scene: Scene, rootUrl: string = "", nodeMaterial?: NodeMaterial): Promise<NodeMaterial> {
         return new Promise((resolve, reject) => {
             var request = new WebRequest();
             request.addEventListener("readystatechange", () => {
@@ -1347,9 +1353,14 @@ export class NodeMaterial extends PushMaterial {
                     if (request.status == 200) {
                         var snippet = JSON.parse(JSON.parse(request.responseText).jsonPayload);
                         let serializationObject = JSON.parse(snippet.nodeMaterial);
-                        let nodeMaterial = SerializationHelper.Parse(() => new NodeMaterial(snippetId, scene), serializationObject, scene, rootUrl);
+
+                        if (!nodeMaterial) {
+                            nodeMaterial = SerializationHelper.Parse(() => new NodeMaterial(snippetId, scene), serializationObject, scene, rootUrl);
+                        }
 
                         nodeMaterial.loadFromSerialization(serializationObject);
+                        nodeMaterial.snippetId = snippetId;
+
                         try {
                             nodeMaterial.build(true);
                             resolve(nodeMaterial);

+ 15 - 13
src/Materials/Textures/Packer/packer.ts

@@ -10,6 +10,7 @@ import { Vector2 } from "../../../Maths/math.vector";
 import { Color3, Color4 } from "../../../Maths/math.color";
 import { TexturePackerFrame } from "./frame";
 import { Logger } from "../../../Misc/logger";
+import { Tools } from '../../../Misc/tools';
 
 /**
 * Defines the basic options interface of a TexturePacker
@@ -175,7 +176,7 @@ export class TexturePacker{
          * Run through the options and set what ever defaults are needed that where not declared.
          */
         this.options = options;
-        this.options.map = this.options.map || [
+        this.options.map = this.options.map ?? [
                 'ambientTexture',
                 'bumpTexture',
                 'diffuseTexture',
@@ -187,26 +188,26 @@ export class TexturePacker{
                 'specularTexture'
             ];
 
-        this.options.uvsIn = this.options.uvsIn || VertexBuffer.UVKind;
-        this.options.uvsOut = this.options.uvsOut || VertexBuffer.UVKind;
-        this.options.layout = this.options.layout || TexturePacker.LAYOUT_STRIP;
+        this.options.uvsIn = this.options.uvsIn ?? VertexBuffer.UVKind;
+        this.options.uvsOut = this.options.uvsOut ?? VertexBuffer.UVKind;
+        this.options.layout = this.options.layout ?? TexturePacker.LAYOUT_STRIP;
 
         if (this.options.layout === TexturePacker.LAYOUT_COLNUM) {
-            this.options.colnum = this.options.colnum || 8;
+            this.options.colnum = this.options.colnum ?? 8;
         }
 
-        this.options.updateInputMeshes = this.options.updateInputMeshes || true;
-        this.options.disposeSources = this.options.disposeSources || true;
+        this.options.updateInputMeshes = this.options.updateInputMeshes ?? true;
+        this.options.disposeSources = this.options.disposeSources ?? true;
         this._expecting = 0;
 
-        this.options.fillBlanks = this.options.fillBlanks || true;
+        this.options.fillBlanks = this.options.fillBlanks ?? true;
 
         if (this.options.fillBlanks === true) {
-            this.options.customFillColor = this.options.customFillColor || 'black';
+            this.options.customFillColor = this.options.customFillColor ?? 'black';
         }
 
-        this.options.frameSize = this.options.frameSize || 256;
-        this.options.paddingRatio = this.options.paddingRatio || 0.0115;
+        this.options.frameSize = this.options.frameSize ?? 256;
+        this.options.paddingRatio = this.options.paddingRatio ?? 0.0115;
 
         this._paddingValue = Math.ceil(this.options.frameSize * this.options.paddingRatio);
 
@@ -215,10 +216,10 @@ export class TexturePacker{
             this._paddingValue++;
         }
 
-        this.options.paddingMode = this.options.paddingMode || TexturePacker.SUBUV_WRAP;
+        this.options.paddingMode = this.options.paddingMode ?? TexturePacker.SUBUV_WRAP;
 
         if (this.options.paddingMode === TexturePacker.SUBUV_COLOR) {
-            this.options.paddingColor = this.options.paddingColor || new Color4(0, 0, 0, 1.0);
+            this.options.paddingColor = this.options.paddingColor ?? new Color4(0, 0, 0, 1.0);
         }
 
         this.sets = {};
@@ -322,6 +323,7 @@ export class TexturePacker{
                     } else {
                         img.src = setTexture!.url;
                     }
+                    Tools.SetCorsBehavior(img.src, img);
 
                     img.onload = () => {
                         tcx.fillStyle = 'rgba(0,0,0,0)';

+ 3 - 3
src/Misc/assetsManager.ts

@@ -490,7 +490,7 @@ export class TextureAssetTask extends AbstractAssetTask implements ITextureAsset
      * @param name defines the name of the task
      * @param url defines the location of the file to load
      * @param noMipmap defines if mipmap should not be generated (default is false)
-     * @param invertY defines if texture must be inverted on Y axis (default is false)
+     * @param invertY defines if texture must be inverted on Y axis (default is true)
      * @param samplingMode defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
      */
     constructor(
@@ -507,9 +507,9 @@ export class TextureAssetTask extends AbstractAssetTask implements ITextureAsset
          */
         public noMipmap?: boolean,
         /**
-         * Defines if texture must be inverted on Y axis (default is false)
+         * Defines if texture must be inverted on Y axis (default is true)
          */
-        public invertY?: boolean,
+        public invertY: boolean = true,
         /**
          * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
          */