ソースを参照

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

noalak 5 年 前
コミット
416d5b527f
44 ファイル変更2121 行追加85 行削除
  1. 639 0
      Playground/scripts/spriteMap.js
  2. 420 0
      Playground/textures/spriteMap/none_trimmed/Legends_Level_A.json
  3. BIN
      Playground/textures/spriteMap/none_trimmed/Legends_Level_A.png
  4. 2 0
      Playground/textures/spriteMap/none_trimmed/levelStage.tilemaps
  5. 1 1
      dist/preview release/babylon.d.ts
  6. 1 1
      dist/preview release/babylon.js
  7. 24 24
      dist/preview release/babylon.max.js
  8. 1 1
      dist/preview release/babylon.max.js.map
  9. 2 2
      dist/preview release/babylon.module.d.ts
  10. 1 1
      dist/preview release/documentation.d.ts
  11. 1 1
      dist/preview release/glTF2Interface/package.json
  12. 2 2
      dist/preview release/gui/package.json
  13. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.js
  14. 4 3
      dist/preview release/inspector/babylon.inspector.bundle.max.js
  15. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.max.js.map
  16. 1 0
      dist/preview release/inspector/babylon.inspector.d.ts
  17. 3 1
      dist/preview release/inspector/babylon.inspector.module.d.ts
  18. 7 7
      dist/preview release/inspector/package.json
  19. 3 3
      dist/preview release/loaders/package.json
  20. 2 2
      dist/preview release/materialsLibrary/package.json
  21. 2 2
      dist/preview release/nodeEditor/package.json
  22. 1 1
      dist/preview release/package.json
  23. 2 2
      dist/preview release/postProcessesLibrary/package.json
  24. 2 2
      dist/preview release/proceduralTexturesLibrary/package.json
  25. 3 3
      dist/preview release/serializers/package.json
  26. 2 2
      dist/preview release/viewer/babylon.module.d.ts
  27. 5 5
      dist/preview release/viewer/babylon.viewer.js
  28. 1 1
      dist/preview release/viewer/babylon.viewer.max.js
  29. 4 0
      dist/preview release/what's new.md
  30. 2 2
      package.json
  31. 11 1
      src/Cameras/XR/webXRControllerPointerSelection.ts
  32. 12 4
      src/Cameras/XR/webXRDefaultExperience.ts
  33. 10 1
      src/Cameras/XR/webXREnterExitUI.ts
  34. 14 3
      src/Cameras/XR/webXRSessionManager.ts
  35. 2 2
      src/Engines/thinEngine.ts
  36. 5 0
      src/LibDeclarations/webxr.d.ts
  37. 95 0
      src/Shaders/spriteMap.fragment.fx
  38. 78 0
      src/Shaders/spriteMap.fragment.ts
  39. 32 0
      src/Shaders/spriteMap.vertex.fx
  40. 33 0
      src/Shaders/spriteMap.vertex.ts
  41. 91 0
      src/Sprites/ISprites.ts
  42. 2 0
      src/Sprites/index.ts
  43. 27 3
      src/Sprites/spriteManager.ts
  44. 569 0
      src/Sprites/spriteMap.ts

+ 639 - 0
Playground/scripts/spriteMap.js

@@ -0,0 +1,639 @@
+var createScene = function () {
+    var scene = new BABYLON.Scene(engine);
+    // Create camera and light
+    var light = new BABYLON.PointLight("Point", new BABYLON.Vector3(5, 10, 5), scene);
+    var camera = new BABYLON.FreeCamera("Camera", new BABYLON.Vector3(0, 0, -30), scene);
+    
+    // Attach the Controls to the canvas
+    camera.attachControl(canvas, true);
+    
+    // Load the JSON file, for simplicity in this demonstration it is included in-line.
+    let atlasJSON = getJSONFile();
+    
+    // Load the SpriteSheet Associated with the JSON Atlas.
+    let spriteSheet = new BABYLON.Texture('./textures/spriteMap/none_trimmed/Legends_Level_A.png', scene,
+    false, //NoMipMaps
+    false, //InvertY usually false if exported from TexturePacker
+    BABYLON.Texture.NEAREST_NEAREST, //Sampling Mode
+    null, //Onload, you could spin up the sprite map in a function nested here
+    null, //OnError
+    null, //CustomBuffer
+    false, //DeleteBuffer
+    BABYLON.Engine.TEXTURETYPE_RGBA //ImageFormageType RGBA
+    );
+    
+    spriteSheet.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
+    spriteSheet.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE; //Or Wrap, its up to you...
+    
+    let backgroundSize = new BABYLON.Vector2(200,60);
+    
+    let background = new BABYLON.SpriteMap('background', atlasJSON, spriteSheet,
+    {
+        stageSize: backgroundSize,
+        maxAnimationFrames:8,
+        baseTile : 42,
+        layerCount: 2,
+        flipU: true, //Sometimes you gotta flip the depending on the sprite format.
+        colorMultiply : new BABYLON.Vector3(0.3,0.3,0.3)
+    },
+    scene);    
+    
+    //Set all the available tiles to the top left corner of the background for Visual debugging, and reference.
+    for(var i = 0; i<background.spriteCount; i++){
+        background.changeTiles(0, new BABYLON.Vector2(i + 1, backgroundSize.y - 1), i)
+    }
+
+    //TILE, FRAME, NEXT TILE, Timing, Speed
+    //See documentation for Animation Map Information. - TODO
+    let eighth = 1 / 8
+    let speed = 0.005
+    background.addAnimationToTile(1, 0, 2, eighth * 1, speed)
+    background.addAnimationToTile(1, 1, 3, eighth * 2, speed)
+    background.addAnimationToTile(1, 2, 4, eighth * 3, speed)
+    background.addAnimationToTile(1, 3, 5, eighth * 4, speed)
+    background.addAnimationToTile(1, 4, 6, eighth * 5, speed)
+    background.addAnimationToTile(1, 5, 7, eighth * 6, speed)
+    background.addAnimationToTile(1, 6, 8, eighth * 7, speed)
+    background.addAnimationToTile(1, 7, 1, 1, 	  	   speed)
+
+    background.addAnimationToTile(25, 0, 26, eighth * 1, speed)
+    background.addAnimationToTile(25, 1, 27, eighth * 2, speed)
+    background.addAnimationToTile(25, 2, 28, eighth * 3, speed)
+    background.addAnimationToTile(25, 3, 29, eighth * 4, speed)
+    background.addAnimationToTile(25, 4, 30, eighth * 5, speed)
+    background.addAnimationToTile(25, 5, 31, eighth * 6, speed)
+    background.addAnimationToTile(25, 6, 29, eighth * 7, speed)
+    background.addAnimationToTile(25, 7, 25, 1, 	 	 speed)
+
+    background.addAnimationToTile(48, 0, 49, 0.25, 	speed)
+    background.addAnimationToTile(48, 1, 50, 0.5, 	speed)
+    background.addAnimationToTile(48, 2, 51, 0.75, 	speed)
+    background.addAnimationToTile(48, 4, 48, 1, 	speed)
+
+    background.addAnimationToTile(49, 0, 50, 0.25, 	speed * 0.5)
+    background.addAnimationToTile(49, 1, 51, 0.5, 	speed * 0.5)
+    background.addAnimationToTile(49, 2, 48, 0.75, 	speed * 0.5)
+    background.addAnimationToTile(49, 4, 49, 1, 	speed * 0.5)
+
+    background.addAnimationToTile(50, 0, 51, 0.25,  speed * 0.3)
+    background.addAnimationToTile(50, 1, 48, 0.5,   speed * 0.3)
+    background.addAnimationToTile(50, 2, 49, 0.75,  speed * 0.3)
+    background.addAnimationToTile(50, 4, 50, 1, 	speed * 0.3)
+
+    background.position.z = 5;
+
+    //Procedurally Editing the Tiles
+    //Adding Water to BG
+    let tilePositions = []
+    for(let x = 15; x < backgroundSize.x - 15; x++){
+        for(let y = backgroundSize.y - 26; y > 0; y--){
+            if(x % 12 == 0){
+                tilePositions.push(new BABYLON.Vector2(x, y))
+            }
+        }
+    }
+    background.changeTiles(1, tilePositions, 1)
+    
+    //Adding Sewer Drains to BG
+    tilePositions = []
+    for(let x = 15; x < backgroundSize.x - 15; x++){
+        if(x % 12 == 0){
+            tilePositions.push(new BABYLON.Vector2(x, backgroundSize.y - 26))
+        }
+    }
+    background.changeTiles(1, tilePositions, 25)
+    
+    //More Water!
+    tilePositions = []
+    for(let x = 15; x < backgroundSize.x - 15; x++){
+        for(let y = backgroundSize.y - 12; y > 0; y--){
+            if((x + 6) % 12 == 0){
+                tilePositions.push(new BABYLON.Vector2(x, y))
+            }
+        }
+    }
+    
+    background.changeTiles(1, tilePositions, 1);
+
+    tilePositions = [];
+    
+    //Random Array for placing variations of the torches animation.
+    let pTiles = [48, 49, 50, 48, 49, 50, 48];
+    
+    //Making the Base of the level
+    let levelSize = new BABYLON.Vector2(80,40);
+    
+    let levelBase = new BABYLON.SpriteMap('base', atlasJSON, spriteSheet,
+    {
+        stageSize: levelSize,
+        maxAnimationFrames:8,
+        baseTile : 42,
+        layerCount: 2,
+        flipU: true,
+        colorMultiply : new BABYLON.Vector3(0.6,0.6,0.6)
+    },
+    scene);
+    
+    //Duplicating over the animation map from the background system.
+    levelBase.animationMap = background.animationMap
+    
+    
+    //Making a hole.
+    tilePositions = []
+    for(let x = 15; x < levelSize.x - 15; x++){
+        for(let y = levelSize.y - 15; y > 15; y--){
+            tilePositions.push(new BABYLON.Vector2(x, y))
+        }
+    }
+    levelBase.changeTiles(0, tilePositions, 0)
+
+    //Adding Columns
+    tilePositions = []
+    for(let x = 15; x < levelSize.x - 15; x++){
+        for(let y = levelSize.y - 16; y > 16; y--){
+            if(x % 6 == 0){
+                tilePositions.push(new BABYLON.Vector2(x, y))
+            }
+        }
+    }
+    levelBase.changeTiles(0, tilePositions, 23)
+
+    //Adding Torches
+    for(let x = 15; x < levelSize.x - 15; x++){
+        if((x + 6) % 12 == 0){
+            levelBase.changeTiles(1, new BABYLON.Vector2(x, 18),
+            pTiles[Math.floor(Math.random()*pTiles.length)])
+        }
+    }
+
+    //Adding Caps
+    tilePositions = []
+    for(let x =1 5; x < levelSize.x - 15; x++){
+        if(x % 6 == 0){
+         tilePositions.push(new BABYLON.Vector2(x, 16))
+        }
+    }
+    levelBase.changeTiles(0, tilePositions, 24)
+
+    //Adding Bases
+    tilePositions = []
+    for(let x = 15; x < levelSize.x - 15; x++){
+        if(x % 6 == 0){
+            tilePositions.push(new BABYLON.Vector2(x, 25))
+        }
+    }
+    levelBase.changeTiles(0, tilePositions, 22)
+
+    //Now this last section was created like all the last two, except it was later exported from the browser and saved.
+    //This shows how to load from the .tilemaps file
+       
+    levelStage = new BABYLON.SpriteMap('levelStage', atlasJSON, spriteSheet,
+    {
+        stageSize: levelSize,
+        maxAnimationFrames:8,
+        baseTile : 42,
+        layerCount: 2,
+        flipU: true
+    },
+    scene);
+
+    levelStage.loadTileMaps('./textures/spriteMap/none_trimmed/levelStage.tilemaps')
+    levelStage.animationMap = background.animationMap
+    levelStage.position.z = -5   
+
+    //To download .tilemaps file for this SpriteMap uncomment the below line.
+    //levelStage.saveTileMaps();
+	
+    return scene;
+}
+
+const getJSONFile = ()=>{
+    return {"frames": [
+{
+	"filename": "blank.png",
+	"frame": {"x":221,"y":221,"w":1,"h":1},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-0.png",
+	"frame": {"x":1,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-1.png",
+	"frame": {"x":1,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-2.png",
+	"frame": {"x":1,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-3.png",
+	"frame": {"x":1,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-4.png",
+	"frame": {"x":1,"y":141,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-5.png",
+	"frame": {"x":1,"y":176,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-6.png",
+	"frame": {"x":1,"y":211,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-7.png",
+	"frame": {"x":1,"y":246,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large-Column-Light-0.png",
+	"frame": {"x":36,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large-Column-Light-1.png",
+	"frame": {"x":71,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large-Column-Light-2.png",
+	"frame": {"x":106,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large-Column-Light-3.png",
+	"frame": {"x":141,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large_Column-0.png",
+	"frame": {"x":176,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large_Column-1.png",
+	"frame": {"x":211,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large_Column-2.png",
+	"frame": {"x":246,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large_Column-3.png",
+	"frame": {"x":36,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman-Column-0.png",
+	"frame": {"x":36,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman-Column-1.png",
+	"frame": {"x":36,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman-Column-2.png",
+	"frame": {"x":36,"y":141,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman-Column-3.png",
+	"frame": {"x":36,"y":176,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman_Column_Light-0.png",
+	"frame": {"x":36,"y":211,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman_Column_Light-1.png",
+	"frame": {"x":36,"y":246,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman_Column_Light-2.png",
+	"frame": {"x":71,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman_Column_Light-3.png",
+	"frame": {"x":106,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-0.png",
+	"frame": {"x":141,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-1.png",
+	"frame": {"x":176,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-2.png",
+	"frame": {"x":211,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-3.png",
+	"frame": {"x":246,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-4.png",
+	"frame": {"x":71,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-5.png",
+	"frame": {"x":71,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-6.png",
+	"frame": {"x":71,"y":141,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-7.png",
+	"frame": {"x":71,"y":176,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-0.png",
+	"frame": {"x":71,"y":211,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-1.png",
+	"frame": {"x":71,"y":246,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-2.png",
+	"frame": {"x":106,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-3.png",
+	"frame": {"x":106,"y":141,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-4.png",
+	"frame": {"x":106,"y":176,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-5.png",
+	"frame": {"x":106,"y":211,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-6.png",
+	"frame": {"x":106,"y":246,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-7.png",
+	"frame": {"x":141,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-8.png",
+	"frame": {"x":176,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-9.png",
+	"frame": {"x":211,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-10.png",
+	"frame": {"x":106,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-11.png",
+	"frame": {"x":141,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-12.png",
+	"frame": {"x":176,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-13.png",
+	"frame": {"x":211,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-14.png",
+	"frame": {"x":246,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Torch-A-0.png",
+	"frame": {"x":246,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Torch-A-1.png",
+	"frame": {"x":141,"y":141,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Torch-A-2.png",
+	"frame": {"x":141,"y":176,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Torch-A-3.png",
+	"frame": {"x":141,"y":211,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+}],
+"meta": {
+	"app": "https://www.codeandweb.com/texturepacker",
+	"version": "1.0",
+	"image": "Legends_Level_A.png",
+	"format": "RGBA8888",
+	"size": {"w":279,"h":279},
+	"scale": "1",
+	"smartupdate": "$TexturePacker:SmartUpdate:a755ec93daaec56d1c8bcd801e167677:2e759c84cbaf9134b80c1a34b50e5c9c:9f820b9412efc8199e0407f80b8c0011$"
+}
+}
+
+}

+ 420 - 0
Playground/textures/spriteMap/none_trimmed/Legends_Level_A.json

@@ -0,0 +1,420 @@
+{"frames": [
+
+{
+	"filename": "Falling-Water-0.png",
+	"frame": {"x":1,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-1.png",
+	"frame": {"x":1,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-2.png",
+	"frame": {"x":1,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-3.png",
+	"frame": {"x":1,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-4.png",
+	"frame": {"x":1,"y":141,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-5.png",
+	"frame": {"x":1,"y":176,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-6.png",
+	"frame": {"x":1,"y":211,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Falling-Water-7.png",
+	"frame": {"x":1,"y":246,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large-Column-Light-0.png",
+	"frame": {"x":36,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large-Column-Light-1.png",
+	"frame": {"x":71,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large-Column-Light-2.png",
+	"frame": {"x":106,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large-Column-Light-3.png",
+	"frame": {"x":141,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large_Column-0.png",
+	"frame": {"x":176,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large_Column-1.png",
+	"frame": {"x":211,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large_Column-2.png",
+	"frame": {"x":246,"y":1,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Large_Column-3.png",
+	"frame": {"x":36,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman-Column-0.png",
+	"frame": {"x":36,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman-Column-1.png",
+	"frame": {"x":36,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman-Column-2.png",
+	"frame": {"x":36,"y":141,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman-Column-3.png",
+	"frame": {"x":36,"y":176,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman_Column_Light-0.png",
+	"frame": {"x":36,"y":211,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman_Column_Light-1.png",
+	"frame": {"x":36,"y":246,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman_Column_Light-2.png",
+	"frame": {"x":71,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Roman_Column_Light-3.png",
+	"frame": {"x":106,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-0.png",
+	"frame": {"x":141,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-1.png",
+	"frame": {"x":176,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-2.png",
+	"frame": {"x":211,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-3.png",
+	"frame": {"x":246,"y":36,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-4.png",
+	"frame": {"x":71,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-5.png",
+	"frame": {"x":71,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-6.png",
+	"frame": {"x":71,"y":141,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Sewer-Drain-7.png",
+	"frame": {"x":71,"y":176,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-0.png",
+	"frame": {"x":71,"y":211,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-1.png",
+	"frame": {"x":71,"y":246,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-2.png",
+	"frame": {"x":106,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-3.png",
+	"frame": {"x":106,"y":141,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-4.png",
+	"frame": {"x":106,"y":176,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-5.png",
+	"frame": {"x":106,"y":211,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-6.png",
+	"frame": {"x":106,"y":246,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-7.png",
+	"frame": {"x":141,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-8.png",
+	"frame": {"x":176,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-9.png",
+	"frame": {"x":211,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-10.png",
+	"frame": {"x":106,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-11.png",
+	"frame": {"x":141,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-12.png",
+	"frame": {"x":176,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-13.png",
+	"frame": {"x":211,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Stone-Platform-14.png",
+	"frame": {"x":246,"y":71,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Torch-A-0.png",
+	"frame": {"x":246,"y":106,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Torch-A-1.png",
+	"frame": {"x":141,"y":141,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Torch-A-2.png",
+	"frame": {"x":141,"y":176,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+},
+{
+	"filename": "Torch-A-3.png",
+	"frame": {"x":141,"y":211,"w":32,"h":32},
+	"rotated": false,
+	"trimmed": false,
+	"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
+	"sourceSize": {"w":32,"h":32}
+}],
+"meta": {
+	"app": "https://www.codeandweb.com/texturepacker",
+	"version": "1.0",
+	"image": "Legends_Level_A.png",
+	"format": "RGBA8888",
+	"size": {"w":279,"h":279},
+	"scale": "1",
+	"smartupdate": "$TexturePacker:SmartUpdate:a755ec93daaec56d1c8bcd801e167677:2e759c84cbaf9134b80c1a34b50e5c9c:9f820b9412efc8199e0407f80b8c0011$"
+}
+}

BIN
Playground/textures/spriteMap/none_trimmed/Legends_Level_A.png


ファイルの差分が大きいため隠しています
+ 2 - 0
Playground/textures/spriteMap/none_trimmed/levelStage.tilemaps


+ 1 - 1
dist/preview release/babylon.d.ts

@@ -44174,7 +44174,7 @@ declare module BABYLON {
         /**
          * Optional initial tab (default to DebugLayerTab.Properties)
          */
-        initialTab?: DebugLayerTab.Properties;
+        initialTab?: DebugLayerTab;
     }
         interface Scene {
             /**

ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/babylon.js


ファイルの差分が大きいため隠しています
+ 24 - 24
dist/preview release/babylon.max.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/babylon.max.js.map


+ 2 - 2
dist/preview release/babylon.module.d.ts

@@ -45880,7 +45880,7 @@ declare module "babylonjs/Debug/debugLayer" {
         /**
          * Optional initial tab (default to DebugLayerTab.Properties)
          */
-        initialTab?: DebugLayerTab.Properties;
+        initialTab?: DebugLayerTab;
     }
     module "babylonjs/scene" {
         interface Scene {
@@ -113140,7 +113140,7 @@ declare module BABYLON {
         /**
          * Optional initial tab (default to DebugLayerTab.Properties)
          */
-        initialTab?: DebugLayerTab.Properties;
+        initialTab?: DebugLayerTab;
     }
         interface Scene {
             /**

+ 1 - 1
dist/preview release/documentation.d.ts

@@ -44174,7 +44174,7 @@ declare module BABYLON {
         /**
          * Optional initial tab (default to DebugLayerTab.Properties)
          */
-        initialTab?: DebugLayerTab.Properties;
+        initialTab?: DebugLayerTab;
     }
         interface Scene {
             /**

+ 1 - 1
dist/preview release/glTF2Interface/package.json

@@ -1,7 +1,7 @@
 {
     "name": "babylonjs-gltf2interface",
     "description": "A typescript declaration of babylon's gltf2 inteface.",
-    "version": "4.1.0-beta.4",
+    "version": "4.1.0-beta.5",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 2 - 2
dist/preview release/gui/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-gui",
     "description": "The Babylon.js GUI library is an extension you can use to generate interactive user interface. It is build on top of the DynamicTexture.",
-    "version": "4.1.0-beta.4",
+    "version": "4.1.0-beta.5",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.1.0-beta.4"
+        "babylonjs": "4.1.0-beta.5"
     },
     "engines": {
         "node": "*"

ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js


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

@@ -47849,13 +47849,13 @@ var EmbedHostComponent = /** @class */ (function (_super) {
                     react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sceneExplorer_sceneExplorerComponent__WEBPACK_IMPORTED_MODULE_4__["SceneExplorerComponent"], { scene: this.props.scene, extensibilityGroups: this.props.extensibilityGroups, popupMode: true, globalState: this.props.globalState, noHeader: true })),
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { id: "separator" }),
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { id: "bottomPart", style: { marginTop: "4px", overflow: "hidden" } },
-                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_actionTabs_actionTabsComponent__WEBPACK_IMPORTED_MODULE_5__["ActionTabsComponent"], { scene: this.props.scene, popupMode: true, globalState: this.props.globalState, noHeader: true }))));
+                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_actionTabs_actionTabsComponent__WEBPACK_IMPORTED_MODULE_5__["ActionTabsComponent"], { scene: this.props.scene, popupMode: true, globalState: this.props.globalState, noHeader: true, initialTab: this.props.initialTab }))));
         }
         return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { ref: "split", id: "split", className: "noPopup" },
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { id: "topPart", ref: "topPart" },
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sceneExplorer_sceneExplorerComponent__WEBPACK_IMPORTED_MODULE_4__["SceneExplorerComponent"], { scene: this.props.scene, extensibilityGroups: this.props.extensibilityGroups, globalState: this.props.globalState, popupMode: true, noHeader: true })),
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { id: "bottomPart", ref: "bottomPart", style: { marginTop: "4px", overflow: "hidden" } },
-                react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_actionTabs_actionTabsComponent__WEBPACK_IMPORTED_MODULE_5__["ActionTabsComponent"], { scene: this.props.scene, globalState: this.props.globalState, popupMode: true, noHeader: true }))));
+                react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_actionTabs_actionTabsComponent__WEBPACK_IMPORTED_MODULE_5__["ActionTabsComponent"], { scene: this.props.scene, globalState: this.props.globalState, popupMode: true, noHeader: true, initialTab: this.props.initialTab }))));
     };
     EmbedHostComponent.prototype.render = function () {
         var _this = this;
@@ -50259,7 +50259,8 @@ var Inspector = /** @class */ (function () {
                     if (options.popup) {
                         _this._EmbedHostWindow.close();
                     }
-                }
+                },
+                initialTab: options.initialTab
             });
             react_dom__WEBPACK_IMPORTED_MODULE_2__["render"](embedHostElement, this._EmbedHost);
         }

ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.max.js.map


+ 1 - 0
dist/preview release/inspector/babylon.inspector.d.ts

@@ -1797,6 +1797,7 @@ declare module INSPECTOR {
         onClose: () => void;
         onPopup: () => void;
         extensibilityGroups?: BABYLON.IExplorerExtensibilityGroup[];
+        initialTab?: BABYLON.DebugLayerTab;
     }
     export class EmbedHostComponent extends React.Component<IEmbedHostComponentProps> {
         private _once;

+ 3 - 1
dist/preview release/inspector/babylon.inspector.module.d.ts

@@ -2267,7 +2267,7 @@ declare module "babylonjs-inspector/components/embedHost/embedHostComponent" {
     import * as React from "react";
     import { Scene } from "babylonjs/scene";
     import { GlobalState } from "babylonjs-inspector/components/globalState";
-    import { IExplorerExtensibilityGroup } from 'babylonjs/Debug/debugLayer';
+    import { IExplorerExtensibilityGroup, DebugLayerTab } from 'babylonjs/Debug/debugLayer';
     interface IEmbedHostComponentProps {
         scene: Scene;
         globalState: GlobalState;
@@ -2277,6 +2277,7 @@ declare module "babylonjs-inspector/components/embedHost/embedHostComponent" {
         onClose: () => void;
         onPopup: () => void;
         extensibilityGroups?: IExplorerExtensibilityGroup[];
+        initialTab?: DebugLayerTab;
     }
     export class EmbedHostComponent extends React.Component<IEmbedHostComponentProps> {
         private _once;
@@ -4130,6 +4131,7 @@ declare module INSPECTOR {
         onClose: () => void;
         onPopup: () => void;
         extensibilityGroups?: BABYLON.IExplorerExtensibilityGroup[];
+        initialTab?: BABYLON.DebugLayerTab;
     }
     export class EmbedHostComponent extends React.Component<IEmbedHostComponentProps> {
         private _once;

+ 7 - 7
dist/preview release/inspector/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-inspector",
     "description": "The Babylon.js inspector.",
-    "version": "4.1.0-beta.4",
+    "version": "4.1.0-beta.5",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -29,12 +29,12 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.1.0-beta.4",
-        "babylonjs-gui": "4.1.0-beta.4",
-        "babylonjs-loaders": "4.1.0-beta.4",
-        "babylonjs-materials": "4.1.0-beta.4",
-        "babylonjs-serializers": "4.1.0-beta.4",
-        "babylonjs-gltf2interface": "4.1.0-beta.4"
+        "babylonjs": "4.1.0-beta.5",
+        "babylonjs-gui": "4.1.0-beta.5",
+        "babylonjs-loaders": "4.1.0-beta.5",
+        "babylonjs-materials": "4.1.0-beta.5",
+        "babylonjs-serializers": "4.1.0-beta.5",
+        "babylonjs-gltf2interface": "4.1.0-beta.5"
     },
     "devDependencies": {
         "@types/react": "~16.7.3",

+ 3 - 3
dist/preview release/loaders/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-loaders",
     "description": "The Babylon.js file loaders library is an extension you can use to load different 3D file types into a Babylon scene.",
-    "version": "4.1.0-beta.4",
+    "version": "4.1.0-beta.5",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,8 +28,8 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs-gltf2interface": "4.1.0-beta.4",
-        "babylonjs": "4.1.0-beta.4"
+        "babylonjs-gltf2interface": "4.1.0-beta.5",
+        "babylonjs": "4.1.0-beta.5"
     },
     "engines": {
         "node": "*"

+ 2 - 2
dist/preview release/materialsLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-materials",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.1.0-beta.4",
+    "version": "4.1.0-beta.5",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.1.0-beta.4"
+        "babylonjs": "4.1.0-beta.5"
     },
     "engines": {
         "node": "*"

+ 2 - 2
dist/preview release/nodeEditor/package.json

@@ -4,14 +4,14 @@
     },
     "name": "babylonjs-node-editor",
     "description": "The Babylon.js node material editor.",
-    "version": "4.1.0-beta.4",
+    "version": "4.1.0-beta.5",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
     },
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.1.0-beta.4"
+        "babylonjs": "4.1.0-beta.5"
     },
     "files": [
         "babylon.nodeEditor.max.js.map",

+ 1 - 1
dist/preview release/package.json

@@ -7,7 +7,7 @@
     ],
     "name": "babylonjs",
     "description": "Babylon.js is a JavaScript 3D engine based on webgl.",
-    "version": "4.1.0-beta.4",
+    "version": "4.1.0-beta.5",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 2 - 2
dist/preview release/postProcessesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-post-process",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.1.0-beta.4",
+    "version": "4.1.0-beta.5",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.1.0-beta.4"
+        "babylonjs": "4.1.0-beta.5"
     },
     "engines": {
         "node": "*"

+ 2 - 2
dist/preview release/proceduralTexturesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-procedural-textures",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.1.0-beta.4",
+    "version": "4.1.0-beta.5",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.1.0-beta.4"
+        "babylonjs": "4.1.0-beta.5"
     },
     "engines": {
         "node": "*"

+ 3 - 3
dist/preview release/serializers/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-serializers",
     "description": "The Babylon.js serializers library is an extension you can use to serialize Babylon scenes.",
-    "version": "4.1.0-beta.4",
+    "version": "4.1.0-beta.5",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,8 +28,8 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.1.0-beta.4",
-        "babylonjs-gltf2interface": "4.1.0-beta.4"
+        "babylonjs": "4.1.0-beta.5",
+        "babylonjs-gltf2interface": "4.1.0-beta.5"
     },
     "engines": {
         "node": "*"

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

@@ -45880,7 +45880,7 @@ declare module "babylonjs/Debug/debugLayer" {
         /**
          * Optional initial tab (default to DebugLayerTab.Properties)
          */
-        initialTab?: DebugLayerTab.Properties;
+        initialTab?: DebugLayerTab;
     }
     module "babylonjs/scene" {
         interface Scene {
@@ -113140,7 +113140,7 @@ declare module BABYLON {
         /**
          * Optional initial tab (default to DebugLayerTab.Properties)
          */
-        initialTab?: DebugLayerTab.Properties;
+        initialTab?: DebugLayerTab;
     }
         interface Scene {
             /**

ファイルの差分が大きいため隠しています
+ 5 - 5
dist/preview release/viewer/babylon.viewer.js


ファイルの差分が大きいため隠しています
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


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

@@ -151,6 +151,8 @@
 
 - SpritePackedManager extends SpriteManager so that a sprite sheet with different size sprites can be used ([JohnK](https://github.com/BabylonJSGuide))
 - MultiPickSprite and multiPickSpriteWithRay added to sprites ([JohnK](https://github.com/BabylonJSGuide))
+- SpritePackedManager support for JSON Objects that where not stringified, of with the frames parameter accepting Objects and Arrays ([Pryme8](https://github.com/Pryme8))
+- Added `SpriteMap` for creation of grid-based dynamically animated sprite atlas rendering (Beta) ([Pryme8](https://github.com/Pryme8))
 
 ### WebXR / WebVR
 
@@ -169,6 +171,8 @@
 - VRExperienceHelper has now an XR fallback to force XR usage (Beta) ([RaananW](https://github.com/RaananW/))
 - Added option to change the teleportation easing function in the VRExperienceHelper class ([https://github.com/LeoRodz](https://github.com/LeoRodz))
 - Windows motion controller mapping corrected to XR ([RaananW](https://github.com/RaananW/))
+- Pointer-Event simulation for screen target ray mode ([RaananW](https://github.com/RaananW/))
+- New observable that triggers when a session was initialized ([RaananW](https://github.com/RaananW/))
 
 ### Ray
 

+ 2 - 2
package.json

@@ -7,7 +7,7 @@
     ],
     "name": "babylonjs",
     "description": "Babylon.js is a JavaScript 3D engine based on webgl.",
-    "version": "4.1.0-beta.4",
+    "version": "4.1.0-beta.5",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -106,4 +106,4 @@
         "xhr2": "^0.1.4",
         "xmlbuilder": "8.2.2"
     }
-}
+}

+ 11 - 1
src/Cameras/XR/webXRControllerPointerSelection.ts

@@ -63,6 +63,10 @@ export class WebXRControllerPointerSelection {
                             pressed = true;
                         }
                     }
+                    // in screen mode - means finger is on the screen
+                    if (controller.inputSource.targetRayMode === 'screen') {
+                        pressed = true;
+                    }
                     if (pressed) {
                         if (!triggerDown) {
                             scene.simulatePointerDown(pick, { pointerId: id });
@@ -106,7 +110,13 @@ export class WebXRControllerPointerSelection {
             controller.onDisposeObservable.addOnce(() => {
                 laserPointer.dispose();
                 cursorMesh.dispose();
-
+                if (controller.inputSource.targetRayMode === 'screen') {
+                    controller.getWorldPointerRayToRef(this._tmpRay);
+                    let pick = scene.pickWithRay(this._tmpRay);
+                    if (pick) {
+                        scene.simulatePointerUp(pick, { pointerId: id });
+                    }
+                }
                 scene.onBeforeRenderObservable.remove(renderObserver);
             });
         });

+ 12 - 4
src/Cameras/XR/webXRDefaultExperience.ts

@@ -5,7 +5,7 @@ import { WebXRControllerModelLoader } from './webXRControllerModelLoader';
 import { WebXRControllerPointerSelection } from './webXRControllerPointerSelection';
 import { WebXRControllerTeleportation } from './webXRControllerTeleportation';
 import { WebXRRenderTarget } from './webXRTypes';
-import { WebXREnterExitUI } from './webXREnterExitUI';
+import { WebXREnterExitUI, WebXREnterExitUIOptions } from './webXREnterExitUI';
 import { AbstractMesh } from '../../Meshes/abstractMesh';
 import { WebXRManagedOutputCanvasOptions } from './webXRManagedOutputCanvas';
 
@@ -26,7 +26,12 @@ export class WebXRDefaultExperienceOptions {
     /**
      * optional configuration for the output canvas
      */
-    public outputCanvasOptions? : WebXRManagedOutputCanvasOptions;
+    public outputCanvasOptions?: WebXRManagedOutputCanvasOptions;
+
+    /**
+     * optional UI options. This can be used among other to change session mode and reference space type
+     */
+    public uiOptions?: WebXREnterExitUIOptions;
 }
 
 /**
@@ -54,7 +59,7 @@ export class WebXRDefaultExperience {
      */
     public teleportation: WebXRControllerTeleportation;
     /**
-     * Enables ui for enetering/exiting xr
+     * Enables ui for entering/exiting xr
      */
     public enterExitUI: WebXREnterExitUI;
     /**
@@ -88,8 +93,11 @@ export class WebXRDefaultExperience {
             result.renderTarget = result.baseExperience.sessionManager.getWebXRRenderTarget(xrHelper.onStateChangedObservable, options.outputCanvasOptions);
 
             if (!options.disableDefaultUI) {
+                if (options.uiOptions) {
+                    options.uiOptions.renderTarget = options.uiOptions.renderTarget || result.renderTarget;
+                }
                 // Create ui for entering/exiting xr
-                return WebXREnterExitUI.CreateAsync(scene, result.baseExperience, { renderTarget: result.renderTarget }).then((ui) => {
+                return WebXREnterExitUI.CreateAsync(scene, result.baseExperience, options.uiOptions || { renderTarget: result.renderTarget }).then((ui) => {
                     result.enterExitUI = ui;
                 });
             } else {

+ 10 - 1
src/Cameras/XR/webXREnterExitUI.ts

@@ -117,7 +117,16 @@ export class WebXREnterExitUI implements IDisposable {
         });
     }
 
-    private constructor(private scene: Scene, options: WebXREnterExitUIOptions) {
+    /**
+     *
+     * @param scene babylon scene object to use
+     * @param options (read-only) version of the options passed to this UI
+     */
+    private constructor(
+        private scene: Scene,
+        /** version of the options passed to this UI */
+        public options: WebXREnterExitUIOptions
+    ) {
         this._overlay = document.createElement("div");
         this._overlay.style.cssText = "z-index:11;position: absolute; right: 20px;bottom: 50px;";
 

+ 14 - 3
src/Cameras/XR/webXRSessionManager.ts

@@ -31,11 +31,15 @@ export class WebXRSessionManager implements IDisposable {
     /**
      * Fires every time a new xrFrame arrives which can be used to update the camera
      */
-    public onXRFrameObservable: Observable<any> = new Observable<any>();
+    public onXRFrameObservable: Observable<XRFrame> = new Observable<XRFrame>();
     /**
      * Fires when the xr session is ended either by the device or manually done
      */
     public onXRSessionEnded: Observable<any> = new Observable<any>();
+    /**
+     * Fires when the xr session is ended either by the device or manually done
+     */
+    public onXRSessionInit: Observable<XRSession> = new Observable<XRSession>();
 
     /**
      * Underlying xr session
@@ -62,7 +66,10 @@ export class WebXRSessionManager implements IDisposable {
      * Constructs a WebXRSessionManager, this must be initialized within a user action before usage
      * @param scene The scene which the session should be created for
      */
-    constructor(private scene: Scene) {
+    constructor(
+        /** The scene which the session should be created for */
+        public scene: Scene
+    ) {
 
     }
 
@@ -90,6 +97,7 @@ export class WebXRSessionManager implements IDisposable {
     public initializeSessionAsync(xrSessionMode: XRSessionMode, optionalFeatures: any = {}): Promise<XRSession> {
         return this._xrNavigator.xr.requestSession(xrSessionMode, optionalFeatures).then((session: XRSession) => {
             this.session = session;
+            this.onXRSessionInit.notifyObservers(session);
             this._sessionEnded = false;
 
             // handle when the session is ended (By calling session.end or device ends its own session eg. pressing home button on phone)
@@ -158,7 +166,9 @@ export class WebXRSessionManager implements IDisposable {
                 }
                 // Store the XR frame in the manager to be consumed by the XR camera to update pose
                 this.currentFrame = xrFrame;
-                this.onXRFrameObservable.notifyObservers(null);
+                if (xrFrame) {
+                    this.onXRFrameObservable.notifyObservers(xrFrame);
+                }
                 this.scene.getEngine()._renderLoop();
             }
         };
@@ -231,6 +241,7 @@ export class WebXRSessionManager implements IDisposable {
      * Converts the render layer of xrSession to a render target
      * @param session session to create render target for
      * @param scene scene the new render target should be created for
+     * @param baseLayer the webgl layer to create the render target for
      */
     public static _CreateRenderTargetTextureFromSession(session: XRSession, scene: Scene, baseLayer: XRWebGLLayer) {
         if (!baseLayer) {

+ 2 - 2
src/Engines/thinEngine.ts

@@ -131,14 +131,14 @@ export class ThinEngine {
      */
     // Not mixed with Version for tooling purpose.
     public static get NpmPackage(): string {
-        return "babylonjs@4.1.0-beta.4";
+        return "babylonjs@4.1.0-beta.5";
     }
 
     /**
      * Returns the current version of the framework
      */
     public static get Version(): string {
-        return "4.1.0-beta.4";
+        return "4.1.0-beta.5";
     }
 
     /**

+ 5 - 0
src/LibDeclarations/webxr.d.ts

@@ -123,4 +123,9 @@ interface XRInputSourceChangeEvent {
     session: XRSession;
     removed: Array<XRInputSource>;
     added: Array<XRInputSource>;
+}
+
+interface XRInputSourceEvent extends Event {
+    readonly frame: XRFrame;
+    readonly inputSource: XRInputSource;
 }

+ 95 - 0
src/Shaders/spriteMap.fragment.fx

@@ -0,0 +1,95 @@
+precision highp float;
+
+varying vec3 vPosition;
+varying vec2 vUV;
+varying vec2 tUV;
+
+uniform float time;
+uniform float spriteCount;
+uniform sampler2D spriteSheet;
+uniform vec2 spriteMapSize;
+
+uniform vec2 outputSize;
+uniform vec2 stageSize;
+
+uniform float maxAnimationFrames;
+
+uniform sampler2D frameMap;
+uniform sampler2D tileMaps[LAYERS];
+uniform sampler2D animationMap;
+
+uniform vec3 colorMul;
+
+float mt;
+
+float fdStep = 1. / 4.;
+
+mat4 getFrameData(float frameID){
+    float fX = frameID / spriteCount;
+    return mat4(
+        texture(frameMap, vec2(fX, 0.), 0.),
+        texture(frameMap, vec2(fX, fdStep * 1.), 0.),
+        texture(frameMap, vec2(fX, fdStep * 2.), 0.),
+        vec4(0.)
+    );
+}
+
+void main(){
+    vec4 color = vec4(0.);    
+    vec2 tileUV = fract(tUV);
+
+    #ifdef FLIPU
+        tileUV.y = 1.0 - tileUV.y;
+    #endif
+
+    vec2 tileID = floor(tUV);	
+    vec2 sheetUnits = 1. / spriteMapSize;
+    float spriteUnits = 1. / spriteCount;
+    vec2 stageUnits = 1. / stageSize;	
+
+    for(int i = 0; i < LAYERS; i++){	
+    
+        float frameID = texture(tileMaps[i], (tileID + 0.5) / stageSize, 0.).x;		
+
+        vec4 animationData = texture(animationMap, vec2((frameID + 0.5) / spriteCount, 0.), 0.); 
+        
+        if(animationData.y > 0.){
+        
+            mt = mod(time*animationData.z, 1.0);
+            float aFrameSteps = 1. / maxAnimationFrames;
+            
+            for(float f = 0.; f < maxAnimationFrames; f++){
+                if(animationData.y > mt){
+                    frameID = animationData.x;
+                    break;
+                }
+                
+                animationData = texture(animationMap, vec2((frameID + 0.5) / spriteCount, aFrameSteps * f), 0.); 
+            }
+        }
+
+        //Get Animation Frame
+        mat4 frameData = getFrameData(frameID + 0.5);	
+        vec2 frameSize = (frameData[0].wz) / spriteMapSize;    
+        vec2 offset = frameData[0].xy * sheetUnits;	
+        vec2 ratio = frameData[2].xy / frameData[0].wz;
+
+        //rotated
+        if(frameData[2].z == 1.){
+            tileUV.xy = tileUV.yx;
+        }
+
+        if(i == 0){
+            color = texture(spriteSheet, tileUV * frameSize+offset);
+        } else {
+            vec4 nc = texture(spriteSheet, tileUV * frameSize+offset);
+            float alpha = min(color.a + nc.a, 1.0);
+            vec3 mixed = mix(color.xyz, nc.xyz, nc.a);
+            color = vec4(mixed, alpha);
+        }	
+    }
+
+    color.xyz*=colorMul;   
+    
+    gl_FragColor =  color;
+}

+ 78 - 0
src/Shaders/spriteMap.fragment.ts

@@ -0,0 +1,78 @@
+import { Effect } from "../Materials/effect";
+
+let name = 'spriteMapPixelShader';
+let shader = `precision highp float;
+varying vec3 vPosition;
+varying vec2 vUV;
+varying vec2 tUV;
+uniform float time;
+uniform float spriteCount;
+uniform sampler2D spriteSheet;
+uniform vec2 spriteMapSize;
+uniform vec2 outputSize;
+uniform vec2 stageSize;
+uniform float maxAnimationFrames;
+uniform sampler2D frameMap;
+uniform sampler2D tileMaps[LAYERS];
+uniform sampler2D animationMap;
+uniform vec3 colorMul;
+float mt;
+float fdStep=1./4.;
+mat4 getFrameData(float frameID){
+float fX=frameID/spriteCount;
+return mat4(
+texture(frameMap,vec2(fX,0.),0.),
+texture(frameMap,vec2(fX,fdStep*1.),0.),
+texture(frameMap,vec2(fX,fdStep*2.),0.),
+vec4(0.)
+);
+}
+void main(){
+vec4 color=vec4(0.);
+vec2 tileUV=fract(tUV);
+#ifdef FLIPU
+tileUV.y=1.0-tileUV.y;
+#endif
+vec2 tileID=floor(tUV);
+vec2 sheetUnits=1./spriteMapSize;
+float spriteUnits=1./spriteCount;
+vec2 stageUnits=1./stageSize;
+for(int i=0; i<LAYERS; i++){
+float frameID=texture(tileMaps[i],(tileID+0.5)/stageSize,0.).x;
+vec4 animationData=texture(animationMap,vec2((frameID+0.5)/spriteCount,0.),0.);
+if(animationData.y>0.){
+mt=mod(time*animationData.z,1.0);
+float aFrameSteps=1./maxAnimationFrames;
+for(float f=0.; f<maxAnimationFrames; f++){
+if(animationData.y>mt){
+frameID=animationData.x;
+break;
+}
+animationData=texture(animationMap,vec2((frameID+0.5)/spriteCount,aFrameSteps*f),0.);
+}
+}
+
+mat4 frameData=getFrameData(frameID+0.5);
+vec2 frameSize=(frameData[0].wz)/spriteMapSize;
+vec2 offset=frameData[0].xy*sheetUnits;
+vec2 ratio=frameData[2].xy/frameData[0].wz;
+
+if(frameData[2].z == 1.){
+tileUV.xy=tileUV.yx;
+}
+if(i == 0){
+color=texture(spriteSheet,tileUV*frameSize+offset);
+} else {
+vec4 nc=texture(spriteSheet,tileUV*frameSize+offset);
+float alpha=min(color.a+nc.a,1.0);
+vec3 mixed=mix(color.xyz,nc.xyz,nc.a);
+color=vec4(mixed,alpha);
+}
+}
+color.xyz*=colorMul;
+gl_FragColor=color;
+}`;
+
+Effect.ShadersStore[name] = shader;
+/** @hidden */
+export var spriteMapPixelShader = { name, shader };

+ 32 - 0
src/Shaders/spriteMap.vertex.fx

@@ -0,0 +1,32 @@
+precision highp float;
+
+// Attributes
+attribute vec3 position;
+attribute vec3 normal;
+attribute vec2 uv;
+
+//Varyings
+varying vec3 vPosition;
+varying vec2 vUV;
+varying vec2 tUV;
+varying vec2 stageUnits;
+varying vec2 levelUnits;
+varying vec2 tileID;
+
+// Uniforms
+uniform float time;
+uniform mat4 worldViewProjection;
+
+uniform vec2 outputSize;
+uniform vec2 stageSize;
+uniform vec2 spriteMapSize;
+
+uniform float stageScale;
+
+void main() {
+    vec4 p = vec4( position, 1. );
+    vPosition = p.xyz;
+    vUV = uv;
+    tUV = uv * stageSize;	
+    gl_Position = worldViewProjection * p;
+}

+ 33 - 0
src/Shaders/spriteMap.vertex.ts

@@ -0,0 +1,33 @@
+import { Effect } from "../Materials/effect";
+
+let name = 'spriteMapVertexShader';
+let shader = `precision highp float;
+
+attribute vec3 position;
+attribute vec3 normal;
+attribute vec2 uv;
+
+varying vec3 vPosition;
+varying vec2 vUV;
+varying vec2 tUV;
+varying vec2 stageUnits;
+varying vec2 levelUnits;
+varying vec2 tileID;
+
+uniform float time;
+uniform mat4 worldViewProjection;
+uniform vec2 outputSize;
+uniform vec2 stageSize;
+uniform vec2 spriteMapSize;
+uniform float stageScale;
+void main() {
+vec4 p=vec4( position,1. );
+vPosition=p.xyz;
+vUV=uv;
+tUV=uv*stageSize;
+gl_Position=worldViewProjection*p;
+}`;
+
+Effect.ShadersStore[name] = shader;
+/** @hidden */
+export var spriteMapVertexShader = { name, shader };

+ 91 - 0
src/Sprites/ISprites.ts

@@ -0,0 +1,91 @@
+/**
+ * Defines the basic options interface of a Sprite Frame Source Size.
+ */
+export interface ISpriteJSONSpriteSourceSize{
+    /**
+	 * number of the original width of the Frame
+	 */
+    w : number;
+
+    /**
+     * number of the original height of the Frame
+     */
+    h : number;
+}
+
+/**
+ * Defines the basic options interface of a Sprite Frame Data.
+ */
+export interface ISpriteJSONSpriteFrameData{
+    /**
+	 * number of the x offset of the Frame
+	 */
+    x : number;
+
+    /**
+	 * number of the y offset of the Frame
+	 */
+    y : number;
+
+    /**
+	 * number of the width of the Frame
+	 */
+    w : number;
+
+    /**
+     * number of the height of the Frame
+     */
+    h : number;
+}
+
+/**
+ * Defines the basic options interface of a JSON Sprite.
+ */
+export interface ISpriteJSONSprite{
+    /**
+	 * string name of the Frame
+	 */
+    filename : string;
+
+    /**
+	 * ISpriteJSONSpriteFrame basic object of the frame data
+	 */
+    frame : ISpriteJSONSpriteFrameData;
+
+    /**
+    * boolean to flag is the frame was rotated.
+    */
+    rotated : boolean;
+
+    /**
+    * boolean to flag is the frame was trimmed.
+    */
+    trimmed : boolean;
+
+    /**
+	 * ISpriteJSONSpriteFrame basic object of the source data
+	 */
+    spriteSourceSize : ISpriteJSONSpriteFrameData;
+
+    /**
+	 * ISpriteJSONSpriteFrame basic object of the source data
+	 */
+    sourceSize : ISpriteJSONSpriteSourceSize;
+}
+
+/**
+ * Defines the basic options interface of a JSON atlas.
+ */
+export interface ISpriteJSONAtlas{
+
+    /**
+	 * Array of objects that contain the frame data.
+	 */
+    frames: Array<ISpriteJSONSprite>;
+
+    /**
+	 * object basic object containing the sprite meta data.
+	 */
+    meta?: object;
+
+}

+ 2 - 0
src/Sprites/index.ts

@@ -1,4 +1,6 @@
 export * from "./sprite";
+export * from "./ISprites";
 export * from "./spriteManager";
+export * from "./spriteMap";
 export * from "./spritePackedManager";
 export * from "./spriteSceneComponent";

+ 27 - 3
src/Sprites/spriteManager.ts

@@ -155,7 +155,7 @@ export class SpriteManager implements ISpriteManager {
     constructor(
         /** defines the manager's name */
         public name: string,
-        imgUrl: string, capacity: number, cellSize: any, scene: Scene, epsilon: number = 0.01, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, fromPacked: boolean = false, spriteJSON: string | null = null) {
+        imgUrl: string, capacity: number, cellSize: any, scene: Scene, epsilon: number = 0.01, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, fromPacked: boolean = false, spriteJSON: any | null = null) {
         if (!scene._getComponent(SceneComponentConstants.NAME_SPRITE)) {
             scene._addComponent(new SpriteSceneComponent(scene));
         }
@@ -226,11 +226,35 @@ export class SpriteManager implements ISpriteManager {
         }
     }
 
-    private _makePacked(imgUrl: string, spriteJSON: string | null) {
+    private _makePacked(imgUrl: string, spriteJSON: any) {
         if (spriteJSON !== null) {
             try {
-                let celldata = JSON.parse(spriteJSON);
+                //Get the JSON and Check its stucture.  If its an array parse it if its a JSON sring etc...
+                let celldata: any;
+                if (typeof spriteJSON === "string") {
+                    celldata = JSON.parse(spriteJSON);
+                }else {
+                    celldata = spriteJSON;
+                }
+
+                if (celldata.frames.length) {
+                    let frametemp: any = {};
+                    for (let i = 0; i < celldata.frames.length; i++) {
+                        let _f = celldata.frames[i];
+                        if (typeof (Object.keys(_f))[0] !== "string") {
+                            throw new Error("Invalid JSON Format.  Check the frame values and make sure the name is the first parameter.");
+                        }
+
+                        let name: string = _f[(Object.keys(_f))[0]];
+                        frametemp[name] = _f;
+                    }
+                    celldata.frames = frametemp;
+                }
+
                 let spritemap = (<string[]>(<any>Reflect).ownKeys(celldata.frames));
+
+                console.log(spritemap);
+
                 this._spriteMap = spritemap;
                 this._packedAndReady = true;
                 this._cellData = celldata.frames;

+ 569 - 0
src/Sprites/spriteMap.ts

@@ -0,0 +1,569 @@
+import { Engine } from "../Engines/engine";
+import { IDisposable, Scene } from "../scene";
+import { Nullable } from "../types";
+import { Vector2, Vector3 } from "../Maths/math.vector";
+import { Texture } from "../Materials/Textures/texture";
+import { RawTexture } from "../Materials/Textures/rawTexture";
+import { ShaderMaterial } from "../Materials/shaderMaterial";
+import { Mesh } from "../Meshes/mesh";
+import { PickingInfo } from "../Collisions/pickingInfo";
+import { ISpriteJSONSprite, ISpriteJSONAtlas } from "./ISprites";
+
+import "../Meshes/Builders/planeBuilder";
+import "../Shaders/spriteMap.fragment";
+import "../Shaders/spriteMap.vertex";
+
+/**
+ * Defines the basic options interface of a SpriteMap
+ */
+export interface ISpriteMapOptions{
+
+    /**
+	 * Vector2 of the number of cells in the grid.
+	 */
+    stageSize?: Vector2;
+
+    /**
+	 * Vector2 of the size of the output plane in World Units.
+	 */
+    outputSize?: Vector2;
+
+    /**
+	 * Vector3 of the position of the output plane in World Units.
+	 */
+    outputPosition?: Vector3;
+
+    //TODO ROTATION
+
+    /**
+	 * number of layers that the system will reserve in resources.
+	 */
+    layerCount?: number;
+
+    /**
+	 * number of max animation frames a single cell will reserve in resources.
+	 */
+    maxAnimationFrames?: number;
+
+    /**
+	 * number cell index of the base tile when the system compiles.
+	 */
+    baseTile?: number;
+
+    /**
+	* boolean flip the sprite after its been repositioned by the framing data.
+	*/
+    flipU?: boolean;
+
+    /**
+	 * Vector3 scalar of the global RGB values of the SpriteMap.
+	 */
+    colorMultiply?: Vector3;
+
+}
+
+/**
+ * Defines the IDisposable interface in order to be cleanable from resources.
+ */
+export interface ISpriteMap extends IDisposable {
+
+    /**
+	 * String name of the SpriteMap.
+	 */
+    name: string;
+
+    /**
+	 * The JSON Array file from a https://www.codeandweb.com/texturepacker export.  Or similar structure.
+	 */
+    atlasJSON: ISpriteJSONAtlas;
+
+    /**
+	 * Texture of the SpriteMap.
+	 */
+    spriteSheet: Texture;
+
+    /**
+	 * The parameters to initialize the SpriteMap with.
+	 */
+    options: ISpriteMapOptions;
+
+}
+
+/**
+ * Class used to manage a grid restricted sprite deployment on an Output plane.
+ */
+export class SpriteMap implements ISpriteMap {
+
+    /** The Name of the spriteMap */
+    public name: string;
+
+    /** The JSON file with the frame and meta data */
+    public atlasJSON: ISpriteJSONAtlas;
+
+    /** The systems Sprite Sheet Texture */
+    public spriteSheet: Texture;
+
+    /** Arguments passed with the Constructor */
+    public options: ISpriteMapOptions;
+
+    /** Public Sprite Storage array, parsed from atlasJSON */
+    public sprites: Array<ISpriteJSONSprite>;
+
+    /** Returns the Number of Sprites in the System */
+    public get spriteCount(): number {
+        return this.sprites.length;
+    }
+
+    /** Returns the Position of Output Plane*/
+    public get position(): Vector3 {
+        return this._output.position;
+    }
+
+    /** Returns the Position of Output Plane*/
+    public set position(v: Vector3) {
+        this._output.position = v;
+    }
+
+    /** Sets the AnimationMap*/
+    public get animationMap() {
+        return this._animationMap;
+    }
+
+    /** Sets the AnimationMap*/
+    public set animationMap(v: RawTexture) {
+        let buffer = v!._texture!._bufferView;
+        let am = this._createTileAnimationBuffer(buffer);
+        this._animationMap.dispose();
+        this._animationMap = am;
+        this._material.setTexture('animationMap', this._animationMap);
+    }
+
+    /** Scene that the SpriteMap was created in */
+    private _scene: Scene;
+
+    /** Texture Buffer of Float32 that holds tile frame data*/
+    private _frameMap: RawTexture;
+
+    /** Texture Buffers of Float32 that holds tileMap data*/
+    private _tileMaps: RawTexture[];
+
+    /** Texture Buffer of Float32 that holds Animation Data*/
+    private _animationMap: RawTexture;
+
+    /** Custom ShaderMaterial Central to the System*/
+    private _material: ShaderMaterial;
+
+    /** Custom ShaderMaterial Central to the System*/
+    private _output: Mesh;
+
+    /** Systems Time Ticker*/
+    private _time: number;
+
+    /**
+     * Creates a new SpriteMap
+     * @param name defines the SpriteMaps Name
+     * @param atlasJSON is the JSON file that controls the Sprites Frames and Meta
+     * @param spriteSheet is the Texture that the Sprites are on.
+     * @param options a basic deployment configuration
+     * @param scene The Scene that the map is deployed on
+     */
+    constructor(name : string, atlasJSON: ISpriteJSONAtlas, spriteSheet: Texture, options: ISpriteMapOptions, scene : Scene) {
+
+    this.name = name;
+    this.sprites = [];
+    this.atlasJSON = atlasJSON;
+    this.sprites = this.atlasJSON['frames'];
+    this.spriteSheet = spriteSheet;
+
+    /**
+    * Run through the options and set what ever defaults are needed that where not declared.
+    */
+    this.options = options;
+    this.options.stageSize = this.options.stageSize || new Vector2(1, 1);
+    this.options.outputSize = this.options.outputSize || this.options.stageSize;
+    this.options.outputPosition = this.options.outputPosition || Vector3.Zero();
+    this.options.layerCount = this.options.layerCount || 1;
+    this.options.maxAnimationFrames = this.options.maxAnimationFrames || 0;
+    this.options.baseTile = this.options.baseTile || 0;
+    this.options.flipU = this.options.flipU || false;
+    this.options.colorMultiply = this.options.colorMultiply || new Vector3(1, 1, 1);
+
+    this._scene = scene;
+
+    this._frameMap = this._createFrameBuffer();
+
+    this._tileMaps = new Array();
+    for (let i = 0; i < this.options.layerCount; i++) {
+        this._tileMaps.push(this._createTileBuffer(null, i));
+    }
+
+    this._animationMap = this._createTileAnimationBuffer(null);
+
+    let defines = [];
+    defines.push("#define LAYERS " + this.options.layerCount);
+
+    if (this.options.flipU) {
+        defines.push("#define FLIPU");
+    }
+
+    this._material = new ShaderMaterial("spriteMap:" + this.name, this._scene, {
+        vertex: "spriteMap",
+        fragment: "spriteMap",
+    }, {
+        defines,
+        attributes: ["position", "normal", "uv"],
+        uniforms: [
+            "worldViewProjection",
+            "time",
+            'stageSize',
+            'outputSize',
+            'spriteMapSize',
+            'spriteCount',
+            'time',
+            'maxAnimationFrames',
+            'colorMul',
+            'mousePosition',
+            'curTile',
+            'flipU'
+        ],
+        samplers: [
+           "spriteSheet", "frameMap", "tileMaps", "animationMap"
+        ],
+        needAlphaBlending: true
+    });
+
+    this._time = 0;
+
+    this._material.setFloat('spriteCount', this.spriteCount);
+    this._material.setFloat('maxAnimationFrames', this.options.maxAnimationFrames);
+    this._material.setVector2('stageSize', this.options.stageSize);
+    this._material.setVector2('outputSize', this.options.outputSize);
+    this._material.setTexture('spriteSheet', this.spriteSheet);
+    this._material.setVector2('spriteMapSize', new Vector2(1, 1));
+    this._material.setVector3('colorMul', this.options.colorMultiply);
+
+    let tickSave = 0;
+
+    const bindSpriteTexture = () => {
+        if ((this.spriteSheet) && this.spriteSheet.isReady()) {
+            if (this.spriteSheet._texture) {
+                this._material.setVector2('spriteMapSize', new Vector2(this.spriteSheet._texture.baseWidth || 1, this.spriteSheet._texture.baseHeight || 1));
+                return;
+            }
+        }
+        if (tickSave < 100) {
+            setTimeout(() => {tickSave++; bindSpriteTexture(); }, 100);
+        }
+    };
+
+    bindSpriteTexture();
+
+    this._material.setVector3('colorMul', this.options.colorMultiply);
+    this._material.setTexture("frameMap", this._frameMap);
+    this._material.setTextureArray("tileMaps", this._tileMaps);
+    this._material.setTexture("animationMap", this._animationMap);
+    this._material.setFloat('time', this._time);
+
+    this._output = Mesh.CreatePlane(name + ":output", 1, scene, true);
+    this._output.scaling.x = this.options.outputSize.x;
+    this._output.scaling.y = this.options.outputSize.y;
+
+    let obfunction = () => {
+        this._time += this._scene.getEngine().getDeltaTime();
+        this._material.setFloat('time', this._time);
+    };
+
+    this._scene.onBeforeRenderObservable.add(obfunction);
+    this._output.material = this._material;
+
+    }
+
+    /**
+    * Returns tileID location
+    * @returns Vector2 the cell position ID
+    */
+    public getTileID(): Vector2 {
+        let p = this.getMousePosition();
+        p.multiplyInPlace(this.options.stageSize || Vector2.Zero());
+        p.x = Math.floor(p.x);
+        p.y = Math.floor(p.y);
+        return p;
+    }
+
+    /**
+    * Gets the UV location of the mouse over the SpriteMap.
+    * @returns Vector2 the UV position of the mouse interaction
+    */
+    public getMousePosition(): Vector2 {
+        let out = this._output;
+        var pickinfo: Nullable<PickingInfo> = this._scene.pick(this._scene.pointerX, this._scene.pointerY, (mesh) => {
+            if (mesh !== out) {
+                return false;
+            }
+          return true;
+        });
+
+        if (((!pickinfo) || !pickinfo.hit) || !pickinfo.getTextureCoordinates) {
+            return new Vector2(-1, -1);
+        }
+
+        let coords = pickinfo.getTextureCoordinates();
+        if (coords) {
+            return coords;
+        }
+
+        return 	new Vector2(-1, -1);
+    }
+
+    /**
+    * Creates the "frame" texture Buffer
+    * -------------------------------------
+    * Structure of frames
+    *  "filename": "Falling-Water-2.png",
+    * "frame": {"x":69,"y":103,"w":24,"h":32},
+    * "rotated": true,
+    * "trimmed": true,
+    * "spriteSourceSize": {"x":4,"y":0,"w":24,"h":32},
+    * "sourceSize": {"w":32,"h":32}
+    * @returns RawTexture of the frameMap
+    */
+    private _createFrameBuffer(): RawTexture {
+        let data = new Array();
+        //Do two Passes
+        for (let i = 0; i < this.spriteCount; i++) {
+            data.push(0, 0, 0, 0); //frame
+            data.push(0, 0, 0, 0); //spriteSourceSize
+            data.push(0, 0, 0, 0); //sourceSize, rotated, trimmed
+            data.push(0, 0, 0, 0); //Keep it pow2 cause I'm cool like that... it helps with sampling accuracy as well. Plus then we have 4 other parameters for future stuff.
+        }
+        //Second Pass
+        for (let i = 0; i < this.spriteCount; i++) {
+            let f = this.sprites[i]['frame'];
+            let sss = this.sprites[i]['spriteSourceSize'];
+            let ss = this.sprites[i]['sourceSize'];
+            let r = (this.sprites[i]['rotated']) ? 1 : 0;
+            let t = (this.sprites[i]['trimmed']) ? 1 : 0;
+
+            //frame
+            data[i * 4] = f.x;
+            data[i * 4 + 1] = f.y;
+            data[i * 4 + 2] = f.w;
+            data[i * 4 + 3] = f.h;
+            //spriteSourceSize
+            data[i * 4 + (this.spriteCount * 4)] = sss.x;
+            data[i * 4 + 1 + (this.spriteCount * 4)] = sss.y;
+            data[i * 4 + 3 + (this.spriteCount * 4)] = sss.h;
+            //sourceSize, rotated, trimmed
+            data[i * 4 + (this.spriteCount * 8)] = ss.w;
+            data[i * 4 + 1 + (this.spriteCount * 8)] = ss.h;
+            data[i * 4 + 2 + (this.spriteCount * 8)] = r;
+            data[i * 4 + 3 + (this.spriteCount * 8)] = t ;
+        }
+
+        let floatArray = new Float32Array(data);
+
+        let t = RawTexture.CreateRGBATexture(
+        floatArray,
+        this.spriteCount,
+        4,
+        this._scene,
+        false,
+        false,
+        Texture.NEAREST_NEAREST,
+        Engine.TEXTURETYPE_FLOAT
+        );
+
+        return t;
+    }
+
+    /**
+    * Creates the tileMap texture Buffer
+    * @param buffer normally and array of numbers, or a false to generate from scratch
+    * @param _layer indicates what layer for a logic trigger dealing with the baseTile.  The system uses this
+    * @returns RawTexture of the tileMap
+    */
+    private _createTileBuffer(buffer: any, _layer: number = 0): RawTexture {
+
+        let data = new Array();
+        let _ty = (this.options.stageSize!.y) || 0;
+        let _tx = (this.options.stageSize!.x) || 0;
+
+        if (!buffer) {
+            let bt = this.options.baseTile;
+            if (_layer != 0) {
+                bt = 0;
+            }
+
+            for (let y = 0; y < _ty; y++) {
+                for (let x = 0; x < _tx * 4; x += 4) {
+                    data.push(bt, 0, 0, 0);
+                }
+            }
+        } else {
+            data = buffer;
+        }
+
+        let floatArray = new Float32Array(data);
+        let t = RawTexture.CreateRGBATexture(
+        floatArray,
+        _tx,
+        _ty,
+        this._scene,
+        false,
+        false,
+        Texture.NEAREST_NEAREST,
+        Engine.TEXTURETYPE_FLOAT
+        );
+
+        return t;
+    }
+
+    /**
+    * Modifies the data of the tileMaps
+    * @param _layer is the ID of the layer you want to edit on the SpriteMap
+    * @param pos is the iVector2 Coordinates of the Tile
+    * @param tile The SpriteIndex of the new Tile
+    */
+    public changeTiles(_layer: number = 0, pos: Vector2 | Vector2[] , tile: number = 0): void {
+
+        let buffer: Nullable<ArrayBufferView>;
+        buffer = this._tileMaps[_layer]!._texture!._bufferView;
+        if (buffer === null) {
+            return;
+        }
+
+        let p = new Array();
+        if (pos instanceof Vector2) {
+            p.push(pos);
+        } else {
+            p = pos;
+        }
+
+        let _tx = (this.options.stageSize!.x) || 0;
+
+        for (let i = 0; i < p.length; i++) {
+            let _p = p[i];
+            _p.x = Math.floor(_p.x);
+            _p.y = Math.floor(_p.y);
+            let id: number = (_p.x * 4) + (_p.y * (_tx * 4));
+            (buffer as any)[id] = tile;
+        }
+
+        let t = this._createTileBuffer(buffer);
+        this._tileMaps[_layer].dispose();
+        this._tileMaps[_layer] = t;
+        this._material.setTextureArray("tileMap", this._tileMaps);
+    }
+
+    /**
+    * Creates the animationMap texture Buffer
+    * @param buffer normally and array of numbers, or a false to generate from scratch
+    * @returns RawTexture of the animationMap
+    */
+    private _createTileAnimationBuffer(buffer: Nullable<ArrayBufferView>): RawTexture {
+        let data = new Array();
+        if (!buffer) {
+            for (let i = 0; i < this.spriteCount; i++) {
+                data.push(0, 0, 0, 0);
+                let count = 1;
+                while (count < (this.options.maxAnimationFrames || 4)) {
+                    data.push(0, 0, 0, 0);
+                    count++;
+                }
+            }
+        } else {
+            data = new Array(buffer);
+        }
+
+        let floatArray = new Float32Array(data);
+        let t = RawTexture.CreateRGBATexture(
+        floatArray,
+        this.spriteCount,
+        (this.options.maxAnimationFrames || 4),
+        this._scene,
+        false,
+        false,
+        Texture.NEAREST_NEAREST,
+        Engine.TEXTURETYPE_FLOAT
+        );
+
+        return t;
+    }
+    /**
+    * Modifies the data of the animationMap
+    * @param cellID is the Index of the Sprite
+    * @param _frame is the target Animation frame
+    * @param toCell is the Target Index of the next frame of the animation
+    * @param time is a value between 0-1 that is the trigger for when the frame should change tiles
+    * @param speed is a global scalar of the time variable on the map.
+    */
+    public addAnimationToTile(cellID: number = 0, _frame: number = 0, toCell: number = 0, time: number = 0, speed: number = 1): void {
+        let buffer: any = this._animationMap!._texture!._bufferView;
+        let id: number = (cellID * 4) + (this.spriteCount * 4 * _frame);
+        if (!buffer) {
+            return;
+        }
+        buffer[id || 0] = toCell;
+        buffer[id + 1 || 0] = time;
+        buffer[id + 2 || 0] = speed;
+        let t = this._createTileAnimationBuffer(buffer);
+        this._animationMap.dispose();
+        this._animationMap = t;
+        this._material.setTexture("animationMap", this._animationMap);
+    }
+
+    /**
+    * Exports the .tilemaps file
+    */
+    public saveTileMaps(): void {
+        let maps = '';
+        for (var i = 0; i < this._tileMaps.length; i++) {
+            if (i > 0) {maps += '\n\r'; }
+
+            maps += this._tileMaps[i]!._texture!._bufferView!.toString();
+        }
+        var hiddenElement = document.createElement('a');
+        hiddenElement.href = 'data:octet/stream;charset=utf-8,' + encodeURI(maps);
+        hiddenElement.target = '_blank';
+        hiddenElement.download = this.name + '.tilemaps';
+        hiddenElement.click();
+        hiddenElement.remove();
+    }
+
+    /**
+    * Imports the .tilemaps file
+    * @param url of the .tilemaps file
+    */
+    public loadTileMaps(url : string) : void {
+        let xhr = new XMLHttpRequest();
+        xhr.open("GET", url);
+
+        let _lc =  this.options!.layerCount || 0;
+
+        xhr.onload = () =>
+        {
+            let data = xhr.response.split('\n\r');
+            for (let i = 0; i < _lc; i++) {
+                let d = (data[i].split(',')).map(Number);
+                let t = this._createTileBuffer(d);
+                this._tileMaps[i].dispose();
+                this._tileMaps[i] = t;
+            }
+            this._material.setTextureArray("tileMap", this._tileMaps);
+        };
+        xhr.send();
+    }
+
+    /**
+     * Release associated resources
+     */
+    public dispose(): void {
+        this._output.dispose();
+        this._material.dispose();
+        this._animationMap.dispose();
+        this._tileMaps.forEach((tm) => {
+            tm.dispose();
+        });
+        this._frameMap.dispose();
+    }
+}