Bläddra i källkod

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

# Conflicts:
#	dist/preview release/babylon.core.js
#	dist/preview release/babylon.d.ts
#	dist/preview release/babylon.js
#	dist/preview release/babylon.max.js
#	dist/preview release/babylon.noworker.js
davrous 8 år sedan
förälder
incheckning
b1cb781ab2
82 ändrade filer med 8501 tillägg och 4343 borttagningar
  1. 36 6
      .vscode/launch.json
  2. 3 2
      Babylon.csproj
  3. 18 4
      Exporters/3ds Max/BabylonExport.Entities/BabylonParticleSystem.cs
  4. 1 1
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Library/manager.bjs
  5. BIN
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Plugins/BabylonExport.Entities.dll
  6. 335 0
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Shader/UnitySpecular.shader
  7. 346 0
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Shader/UnityStandard.shader
  8. 2 2
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/BabylonPhysicsState.cs
  9. 480 0
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/BabylonShaderInterface.cs
  10. 3 5
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/ExportationOptions.cs
  11. 2 0
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/ExporterMetadata.cs
  12. 16 22
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/ExporterWindow.cs
  13. 11 7
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/SceneBuilder.Cameras.cs
  14. 101 21
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/SceneBuilder.Materials.cs
  15. 14 13
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/SceneBuilder.cs
  16. 6 0
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/Tools.cs
  17. 3 0
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Templates/Config/index.html
  18. 93 79
      Exporters/Unity 5/EditorToolkit/Assets/Babylon/Templates/Shaders/amiga.template
  19. BIN
      Exporters/Unity 5/EditorToolkit/Redist/Asset Store-5.x/BabylonJS/BabylonJS Editor Toolkit.unitypackage
  20. 59 0
      Playground/scripts/instanced bones.js
  21. 2 1
      Playground/scripts/scripts.txt
  22. 4 2
      Tools/Gulp/config.json
  23. 0 1
      Tools/Gulp/custom.config.json
  24. 2 1
      Tools/Npm/getfiles.bat
  25. 3 2
      Web.config
  26. BIN
      assets/meshes/Dude/0.jpg
  27. BIN
      assets/meshes/Dude/1.jpg
  28. BIN
      assets/meshes/Dude/2.jpg
  29. BIN
      assets/meshes/Dude/3.jpg
  30. 1 0
      assets/meshes/Dude/dude.babylon
  31. 5 0
      assets/meshes/skull.babylon
  32. BIN
      assets/textures/sun.png
  33. 1 1
      bower.json
  34. 311 0
      canvas2D/src/Engine/babylon.atlasPicture.ts
  35. 11 2
      canvas2D/src/Engine/babylon.canvas2d.ts
  36. 467 78
      src/Materials/Textures/babylon.fontTexture.ts
  37. 8 1
      canvas2D/src/Engine/babylon.prim2dBase.ts
  38. 16 9
      canvas2D/src/Engine/babylon.renderablePrim2d.ts
  39. 163 93
      canvas2D/src/Engine/babylon.sprite2d.ts
  40. 14 6
      canvas2D/src/Engine/babylon.text2d.ts
  41. 51 1
      canvas2D/src/shaders/sprite2d.fragment.fx
  42. 31 8
      canvas2D/src/shaders/sprite2d.vertex.fx
  43. 25 25
      dist/preview release/babylon.core.js
  44. 2402 2394
      dist/preview release/babylon.d.ts
  45. 36 36
      dist/preview release/babylon.js
  46. 633 812
      dist/preview release/babylon.max.js
  47. 35 35
      dist/preview release/babylon.noworker.js
  48. 383 22
      dist/preview release/canvas2D/babylon.canvas2d.d.ts
  49. 1284 145
      dist/preview release/canvas2D/babylon.canvas2d.js
  50. 10 10
      dist/preview release/canvas2D/babylon.canvas2d.min.js
  51. 2 2
      dist/preview release/inspector/babylon.inspector.bundle.js
  52. 7 1
      dist/preview release/inspector/babylon.inspector.js
  53. 2 2
      dist/preview release/inspector/babylon.inspector.min.js
  54. 3 1
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  55. 72 42
      dist/preview release/loaders/babylon.glTFFileLoader.js
  56. 2 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  57. 16 0
      dist/preview release/what's new.md
  58. 7 1
      inspector/src/tabs/StatsTab.ts
  59. 85 46
      loaders/src/glTF/babylon.glTFFileLoader.ts
  60. 5 1
      loaders/src/glTF/babylon.glTFFileLoaderInterfaces.ts
  61. 3 3
      src/Animations/babylon.animatable.ts
  62. 4 0
      src/Audio/babylon.sound.ts
  63. 1 0
      src/Cameras/babylon.camera.ts
  64. 53 7
      src/Materials/babylon.effect.ts
  65. 5 0
      src/Materials/babylon.pbrMaterial.ts
  66. 5 0
      src/Materials/babylon.standardMaterial.ts
  67. 3 2
      src/Math/babylon.math.ts
  68. 90 2
      src/Mesh/babylon.abstractMesh.ts
  69. 39 8
      src/Mesh/babylon.geometry.ts
  70. 1 1
      src/Mesh/babylon.instancedMesh.ts
  71. 22 2
      src/Mesh/babylon.mesh.ts
  72. 33 5
      src/Particles/babylon.particleSystem.ts
  73. 1 25
      src/Physics/Plugins/babylon.cannonJSPlugin.ts
  74. 2 2
      src/Physics/Plugins/babylon.oimoJSPlugin.ts
  75. 1 1
      src/Physics/babylon.physicsEngine.ts
  76. 10 7
      src/Physics/babylon.physicsImpostor.ts
  77. 3 3
      src/Shaders/volumetricLightScattering.fragment.fx
  78. 142 0
      src/Tools/babylon.khronosTextureContainer.ts
  79. 407 297
      src/babylon.engine.ts
  80. 14 0
      src/babylon.mixins.ts
  81. 17 17
      tests/Canvas2d/Jasmine/chutzpah.json
  82. 17 17
      tests/Tools/Jasmine/chutzpah.json

+ 36 - 6
.vscode/launch.json

@@ -8,7 +8,22 @@
             "url": "http://localhost:1338/Playground/index-local.html",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
-            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug"
+            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
+            "runtimeArgs": [
+                "--enable-unsafe-es3-apis" 
+            ]
+        },        
+        {
+            "name": "Launch playground (Chrome+WebGL 1.0 forced)",
+            "type": "chrome",
+            "request": "launch",
+            "url": "http://localhost:1338/Playground/index-local.html",
+            "webRoot": "${workspaceRoot}/",
+            "sourceMaps": true,
+            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
+            "runtimeArgs": [
+                "--disable-es3-apis" 
+            ]
         },
         {
             "name": "Launch Materials Library (Chrome)",
@@ -17,7 +32,10 @@
             "url": "http://localhost:1338/materialsLibrary/index.html",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
-            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug"
+            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
+            "runtimeArgs": [
+                "--enable-unsafe-es3-apis" 
+            ]
         },
         {
             "name": "Launch Post Processes Library (Chrome)",
@@ -26,7 +44,10 @@
             "url": "http://localhost:1338/postProcessLibrary/index.html",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
-            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug"
+            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
+            "runtimeArgs": [
+                "--enable-unsafe-es3-apis" 
+            ]
         },
         {
             "name": "Launch Procedural Textures Library (Chrome)",
@@ -35,7 +56,10 @@
             "url": "http://localhost:1338/proceduralTexturesLibrary/index.html",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
-            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug"
+            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
+            "runtimeArgs": [
+                "--enable-unsafe-es3-apis" 
+            ]
         },
         {
             "name": "Launch Inspector (Chrome)",
@@ -44,7 +68,10 @@
             "url": "http://localhost:1338/inspector/index.html",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
-            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug"
+            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
+            "runtimeArgs": [
+                "--enable-unsafe-es3-apis" 
+            ]
         },
         {
             "name": "Launch Local Dev (Chrome)",
@@ -53,7 +80,10 @@
             "url": "http://localhost:1338/localDev/index.html",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
-            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug"
+            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
+            "runtimeArgs": [
+                "--enable-unsafe-es3-apis" 
+            ]
         }
     ]
 }

+ 3 - 2
Babylon.csproj

@@ -24,7 +24,7 @@
     <SccLocalPath>SAK</SccLocalPath>
     <SccAuxPath>SAK</SccAuxPath>
     <SccProvider>SAK</SccProvider>
-    <TypeScriptToolsVersion>1.8</TypeScriptToolsVersion>
+    <TypeScriptToolsVersion>2.1</TypeScriptToolsVersion>
     <UseGlobalApplicationHostFile />
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -154,7 +154,7 @@
     <TypeScriptCompile Include="src\Materials\Textures\babylon.colorGradingTexture.ts" />
     <TypeScriptCompile Include="src\Materials\Textures\babylon.cubeTexture.ts" />
     <TypeScriptCompile Include="src\Materials\Textures\babylon.dynamicTexture.ts" />
-    <TypeScriptCompile Include="src\Materials\Textures\babylon.fontTexture.ts" />
+    <TypeScriptCompile Include="canvas2D\src\Engine\babylon.fontTexture.ts" />
     <TypeScriptCompile Include="src\Materials\Textures\babylon.mapTexture.ts" />
     <TypeScriptCompile Include="src\Materials\Textures\babylon.refractionTexture.ts" />
     <TypeScriptCompile Include="src\Materials\Textures\babylon.mirrorTexture.ts" />
@@ -173,6 +173,7 @@
     <TypeScriptCompile Include="src\Tools\babylon.decorators.ts" />
     <TypeScriptCompile Include="src\Tools\babylon.dynamicFloatArray.ts" />
     <TypeScriptCompile Include="src\Tools\babylon.earcut.ts" />
+    <TypeScriptCompile Include="src\Tools\babylon.khronosTextureContainer.ts" />
     <TypeScriptCompile Include="src\Tools\babylon.observable.ts" />
     <TypeScriptCompile Include="src\Tools\babylon.rectPackingMap.ts" />
     <TypeScriptCompile Include="src\Tools\babylon.stringDictionary.ts" />

+ 18 - 4
Exporters/3ds Max/BabylonExport.Entities/BabylonParticleSystem.cs

@@ -12,6 +12,9 @@ namespace BabylonExport.Entities
         public bool preventAutoStart { get; set; }
 
         [DataMember]
+        public bool autoAnimate { get; set; }
+
+        [DataMember]
         public string emitterId { get; set; }
 
         [DataMember]
@@ -39,16 +42,13 @@ namespace BabylonExport.Entities
         public float[] colorDead { get; set; }
 
         [DataMember]
-        public float deadAlpha { get; set; }
-
-        [DataMember]
         public float emitRate { get; set; }
 
         [DataMember]
         public float updateSpeed { get; set; }
 
         [DataMember]
-        public int targetStopFrame { get; set; }
+        public float targetStopDuration { get; set; }
 
         [DataMember]
         public float minEmitPower { get; set; }
@@ -88,5 +88,19 @@ namespace BabylonExport.Entities
 
         [DataMember]
         public bool linkToEmitter { get; set; }
+
+        [DataMember]
+        public object[] animations { get; set; }
+
+        [DataMember]
+        public object customShader { get; set; }
+
+        public BabylonParticleSystem()
+        {
+            this.preventAutoStart = true;
+            this.autoAnimate = false;
+            this.animations = null;
+            this.customShader = null;
+        }
     }
 }

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Library/manager.bjs


BIN
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Plugins/BabylonExport.Entities.dll


+ 335 - 0
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Shader/UnitySpecular.shader

@@ -0,0 +1,335 @@
+Shader "BabylonJS/Materials/PBR Material (Specular)"
+{
+	Properties
+	{
+		_Color("Color", Color) = (1,1,1,1)
+		_MainTex("Albedo", 2D) = "white" {}
+		
+		_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
+
+		_Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
+		_GlossMapScale("Smoothness Factor", Range(0.0, 1.0)) = 1.0
+		[Enum(Specular Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel ("Smoothness texture channel", Float) = 0
+
+		_SpecColor("Specular", Color) = (0.2,0.2,0.2)
+		_SpecGlossMap("Specular", 2D) = "white" {}
+		[ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0
+		[ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0
+
+		_BumpScale("Scale", Float) = 1.0
+		_BumpMap("Normal Map", 2D) = "bump" {}
+
+		_Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02
+		_ParallaxMap ("Height Map", 2D) = "black" {}
+
+		_OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
+		_OcclusionMap("Occlusion", 2D) = "white" {}
+
+		_EmissionColor("Color", Color) = (0,0,0)
+		_EmissionMap("Emission", 2D) = "white" {}
+		
+		_DetailMask("Detail Mask", 2D) = "white" {}
+
+		_DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {}
+		_DetailNormalMapScale("Scale", Float) = 1.0
+		_DetailNormalMap("Normal Map", 2D) = "bump" {}
+
+		[Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0
+
+		// Babylon Properties (Lighting & Blending)
+		[Enum(Disable,0,Additive,1,Combine,2,Subtract,3,Multiply,4,Maximized,5,OneOne,6)] _AlphaMode ("Alpha Blending Mode", int) = 2
+		[ToggleOff] _BackFaceCulling("Back Face Culling", Int) = 1
+		[ToggleOff] _DisableLighting("Disable Surface Lighting", Int) = 0
+		[ToggleOff] _UseEmissiveAsIllumination("Use Emissive Illumination", Int) = 0
+
+		// Blending state
+		[HideInInspector] _Mode ("__mode", Float) = 0.0
+		[HideInInspector] _SrcBlend ("__src", Float) = 1.0
+		[HideInInspector] _DstBlend ("__dst", Float) = 0.0
+		[HideInInspector] _ZWrite ("__zw", Float) = 1.0
+	}
+
+	CGINCLUDE
+		#define UNITY_SETUP_BRDF_INPUT SpecularSetup
+	ENDCG
+
+	SubShader
+	{
+		Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
+		LOD 300
+	
+
+		// ------------------------------------------------------------------
+		//  Base forward pass (directional light, emission, lightmaps, ...)
+		Pass
+		{
+			Name "FORWARD" 
+			Tags { "LightMode" = "ForwardBase" }
+
+			Blend [_SrcBlend] [_DstBlend]
+			ZWrite [_ZWrite]
+
+			CGPROGRAM
+			#pragma target 3.0
+
+			// -------------------------------------
+
+			#pragma shader_feature _NORMALMAP
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _EMISSION
+			#pragma shader_feature _SPECGLOSSMAP
+			#pragma shader_feature ___ _DETAIL_MULX2
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
+			#pragma shader_feature _ _GLOSSYREFLECTIONS_OFF
+			#pragma shader_feature _PARALLAXMAP
+
+			#pragma multi_compile_fwdbase
+			#pragma multi_compile_fog
+
+			#pragma vertex vertBase
+			#pragma fragment fragBase
+			#include "UnityStandardCoreForward.cginc"
+
+			ENDCG
+		}
+		// ------------------------------------------------------------------
+		//  Additive forward pass (one light per pass)
+		Pass
+		{
+			Name "FORWARD_DELTA"
+			Tags { "LightMode" = "ForwardAdd" }
+			Blend [_SrcBlend] One
+			Fog { Color (0,0,0,0) } // in additive pass fog should be black
+			ZWrite Off
+			ZTest LEqual
+
+			CGPROGRAM
+			#pragma target 3.0
+
+			// -------------------------------------
+
+			#pragma shader_feature _NORMALMAP
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _SPECGLOSSMAP
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
+			#pragma shader_feature ___ _DETAIL_MULX2
+			#pragma shader_feature _PARALLAXMAP
+
+			#pragma multi_compile_fwdadd_fullshadows
+			#pragma multi_compile_fog
+
+			#pragma vertex vertAdd
+			#pragma fragment fragAdd
+			#include "UnityStandardCoreForward.cginc"
+
+			ENDCG
+		}
+		// ------------------------------------------------------------------
+		//  Shadow rendering pass
+		Pass {
+			Name "ShadowCaster"
+			Tags { "LightMode" = "ShadowCaster" }
+
+			ZWrite On ZTest LEqual
+
+			CGPROGRAM
+			#pragma target 3.0
+
+			// -------------------------------------
+
+
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _SPECGLOSSMAP
+			#pragma shader_feature _PARALLAXMAP
+			#pragma multi_compile_shadowcaster
+
+			#pragma vertex vertShadowCaster
+			#pragma fragment fragShadowCaster
+
+			#include "UnityStandardShadow.cginc"
+
+			ENDCG
+		}
+		// ------------------------------------------------------------------
+		//  Deferred pass
+		Pass
+		{
+			Name "DEFERRED"
+			Tags { "LightMode" = "Deferred" }
+
+			CGPROGRAM
+			#pragma target 3.0
+			#pragma exclude_renderers nomrt
+
+
+			// -------------------------------------
+
+			#pragma shader_feature _NORMALMAP
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _EMISSION
+			#pragma shader_feature _SPECGLOSSMAP
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
+			#pragma shader_feature ___ _DETAIL_MULX2
+			#pragma shader_feature _PARALLAXMAP
+
+			#pragma multi_compile ___ UNITY_HDR_ON
+			#pragma multi_compile ___ LIGHTMAP_ON
+			#pragma multi_compile ___ DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
+			#pragma multi_compile ___ DYNAMICLIGHTMAP_ON
+
+			#pragma vertex vertDeferred
+			#pragma fragment fragDeferred
+
+			#include "UnityStandardCore.cginc"
+
+			ENDCG
+		}
+
+		// ------------------------------------------------------------------
+		// Extracts information for lightmapping, GI (emission, albedo, ...)
+		// This pass it not used during regular rendering.
+		Pass
+		{
+			Name "META" 
+			Tags { "LightMode"="Meta" }
+
+			Cull Off
+
+			CGPROGRAM
+			#pragma vertex vert_meta
+			#pragma fragment frag_meta
+
+			#pragma shader_feature _EMISSION
+			#pragma shader_feature _SPECGLOSSMAP
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature ___ _DETAIL_MULX2
+
+			#include "UnityStandardMeta.cginc"
+			ENDCG
+		}
+	}
+
+	SubShader
+	{
+		Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
+		LOD 150
+
+		// ------------------------------------------------------------------
+		//  Base forward pass (directional light, emission, lightmaps, ...)
+		Pass
+		{
+			Name "FORWARD" 
+			Tags { "LightMode" = "ForwardBase" }
+
+			Blend [_SrcBlend] [_DstBlend]
+			ZWrite [_ZWrite]
+
+			CGPROGRAM
+			#pragma target 2.0
+			
+			#pragma shader_feature _NORMALMAP
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _EMISSION 
+			#pragma shader_feature _SPECGLOSSMAP
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
+			#pragma shader_feature _ _GLOSSYREFLECTIONS_OFF
+			#pragma shader_feature ___ _DETAIL_MULX2
+			// SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP
+
+			#pragma skip_variants SHADOWS_SOFT DYNAMICLIGHTMAP_ON DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
+			
+			#pragma multi_compile_fwdbase
+			#pragma multi_compile_fog
+
+			#pragma vertex vertBase
+			#pragma fragment fragBase
+			#include "UnityStandardCoreForward.cginc"
+
+			ENDCG
+		}
+		// ------------------------------------------------------------------
+		//  Additive forward pass (one light per pass)
+		Pass
+		{
+			Name "FORWARD_DELTA"
+			Tags { "LightMode" = "ForwardAdd" }
+			Blend [_SrcBlend] One
+			Fog { Color (0,0,0,0) } // in additive pass fog should be black
+			ZWrite Off
+			ZTest LEqual
+			
+			CGPROGRAM
+			#pragma target 2.0
+
+			#pragma shader_feature _NORMALMAP
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _SPECGLOSSMAP
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
+			#pragma shader_feature ___ _DETAIL_MULX2
+			// SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP
+			#pragma skip_variants SHADOWS_SOFT
+			
+			#pragma multi_compile_fwdadd_fullshadows
+			#pragma multi_compile_fog
+			
+			#pragma vertex vertAdd
+			#pragma fragment fragAdd
+			#include "UnityStandardCoreForward.cginc"
+
+			ENDCG
+		}
+		// ------------------------------------------------------------------
+		//  Shadow rendering pass
+		Pass {
+			Name "ShadowCaster"
+			Tags { "LightMode" = "ShadowCaster" }
+			
+			ZWrite On ZTest LEqual
+
+			CGPROGRAM
+			#pragma target 2.0
+
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _SPECGLOSSMAP
+			#pragma skip_variants SHADOWS_SOFT
+			#pragma multi_compile_shadowcaster
+
+			#pragma vertex vertShadowCaster
+			#pragma fragment fragShadowCaster
+
+			#include "UnityStandardShadow.cginc"
+
+			ENDCG
+		}
+		// ------------------------------------------------------------------
+		// Extracts information for lightmapping, GI (emission, albedo, ...)
+		// This pass it not used during regular rendering.
+		Pass
+		{
+			Name "META" 
+			Tags { "LightMode"="Meta" }
+
+			Cull Off
+
+			CGPROGRAM
+			#pragma vertex vert_meta
+			#pragma fragment frag_meta
+
+			#pragma shader_feature _EMISSION
+			#pragma shader_feature _SPECGLOSSMAP
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature ___ _DETAIL_MULX2
+
+			#include "UnityStandardMeta.cginc"
+			ENDCG
+		}
+	}
+
+	FallBack "VertexLit"
+	CustomEditor "BabylonShaderInterface"
+}

+ 346 - 0
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Shader/UnityStandard.shader

@@ -0,0 +1,346 @@
+Shader "BabylonJS/Materials/PBR Material"
+{
+	Properties
+	{
+		_Color("Color", Color) = (1,1,1,1)
+		_MainTex("Albedo", 2D) = "white" {}
+		
+		_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
+
+		// Babylon Properties (Roughness)
+		_Roughness("Roughness", Range(0.0, 10.0)) = 1.0
+		[ToggleOff] _UseRoughnessFromMetallicTextureAlpha("From Alpha", Int) = 0
+		[ToggleOff] _UseRoughnessFromMetallicTextureGreen("From Green", Int) = 0
+
+		_Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
+		_GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0
+		[Enum(Metallic Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel ("Smoothness texture channel", Float) = 0
+
+		[Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
+		_MetallicGlossMap("Metallic", 2D) = "white" {}
+
+		[ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0
+		[ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0
+
+		_BumpScale("Scale", Float) = 1.0
+		_BumpMap("Normal Map", 2D) = "bump" {}
+
+		_Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02
+		_ParallaxMap ("Height Map", 2D) = "black" {}
+
+		_OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
+		_OcclusionMap("Occlusion", 2D) = "white" {}
+
+		_EmissionColor("Color", Color) = (0,0,0)
+		_EmissionMap("Emission", 2D) = "white" {}
+		
+		_DetailMask("Detail Mask", 2D) = "white" {}
+
+		_DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {}
+		_DetailNormalMapScale("Scale", Float) = 1.0
+		_DetailNormalMap("Normal Map", 2D) = "bump" {}
+
+		[Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0
+
+		// Babylon Properties (Lighting & Blending)
+		[Enum(Disable,0,Additive,1,Combine,2,Subtract,3,Multiply,4,Maximized,5,OneOne,6)] _AlphaMode ("Alpha Blending Mode", int) = 2
+		[ToggleOff] _BackFaceCulling("Back Face Culling", Int) = 1
+		[ToggleOff] _DisableLighting("Disable Surface Lighting", Int) = 0
+		[ToggleOff] _UseEmissiveAsIllumination("Use Emissive Illumination", Int) = 0
+
+		// Blending state
+		[HideInInspector] _Mode ("__mode", Float) = 0.0
+		[HideInInspector] _SrcBlend ("__src", Float) = 1.0
+		[HideInInspector] _DstBlend ("__dst", Float) = 0.0
+		[HideInInspector] _ZWrite ("__zw", Float) = 1.0
+	}
+
+	CGINCLUDE
+		#define UNITY_SETUP_BRDF_INPUT MetallicSetup
+	ENDCG
+
+	SubShader
+	{
+		Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
+		LOD 300
+	
+
+		// ------------------------------------------------------------------
+		//  Base forward pass (directional light, emission, lightmaps, ...)
+		Pass
+		{
+			Name "FORWARD" 
+			Tags { "LightMode" = "ForwardBase" }
+
+			Blend [_SrcBlend] [_DstBlend]
+			ZWrite [_ZWrite]
+
+			CGPROGRAM
+			#pragma target 3.0
+
+			// -------------------------------------
+
+			#pragma shader_feature _NORMALMAP
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _EMISSION
+			#pragma shader_feature _METALLICGLOSSMAP
+			#pragma shader_feature ___ _DETAIL_MULX2
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
+			#pragma shader_feature _ _GLOSSYREFLECTIONS_OFF
+			#pragma shader_feature _PARALLAXMAP
+
+			#pragma multi_compile_fwdbase
+			#pragma multi_compile_fog
+
+			#pragma vertex vertBase
+			#pragma fragment fragBase
+			#include "UnityStandardCoreForward.cginc"
+
+			ENDCG
+		}
+		// ------------------------------------------------------------------
+		//  Additive forward pass (one light per pass)
+		Pass
+		{
+			Name "FORWARD_DELTA"
+			Tags { "LightMode" = "ForwardAdd" }
+			Blend [_SrcBlend] One
+			Fog { Color (0,0,0,0) } // in additive pass fog should be black
+			ZWrite Off
+			ZTest LEqual
+
+			CGPROGRAM
+			#pragma target 3.0
+
+			// -------------------------------------
+
+
+			#pragma shader_feature _NORMALMAP
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _METALLICGLOSSMAP
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
+			#pragma shader_feature ___ _DETAIL_MULX2
+			#pragma shader_feature _PARALLAXMAP
+
+			#pragma multi_compile_fwdadd_fullshadows
+			#pragma multi_compile_fog
+
+
+			#pragma vertex vertAdd
+			#pragma fragment fragAdd
+			#include "UnityStandardCoreForward.cginc"
+
+			ENDCG
+		}
+		// ------------------------------------------------------------------
+		//  Shadow rendering pass
+		Pass {
+			Name "ShadowCaster"
+			Tags { "LightMode" = "ShadowCaster" }
+
+			ZWrite On ZTest LEqual
+
+			CGPROGRAM
+			#pragma target 3.0
+
+			// -------------------------------------
+
+
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _METALLICGLOSSMAP
+			#pragma shader_feature _PARALLAXMAP
+			#pragma multi_compile_shadowcaster
+
+			#pragma vertex vertShadowCaster
+			#pragma fragment fragShadowCaster
+
+			#include "UnityStandardShadow.cginc"
+
+			ENDCG
+		}
+		// ------------------------------------------------------------------
+		//  Deferred pass
+		Pass
+		{
+			Name "DEFERRED"
+			Tags { "LightMode" = "Deferred" }
+
+			CGPROGRAM
+			#pragma target 3.0
+			#pragma exclude_renderers nomrt
+
+
+			// -------------------------------------
+
+			#pragma shader_feature _NORMALMAP
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _EMISSION
+			#pragma shader_feature _METALLICGLOSSMAP
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
+			#pragma shader_feature ___ _DETAIL_MULX2
+			#pragma shader_feature _PARALLAXMAP
+
+			#pragma multi_compile ___ UNITY_HDR_ON
+			#pragma multi_compile ___ LIGHTMAP_ON
+			#pragma multi_compile ___ DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
+			#pragma multi_compile ___ DYNAMICLIGHTMAP_ON
+
+			#pragma vertex vertDeferred
+			#pragma fragment fragDeferred
+
+			#include "UnityStandardCore.cginc"
+
+			ENDCG
+		}
+
+		// ------------------------------------------------------------------
+		// Extracts information for lightmapping, GI (emission, albedo, ...)
+		// This pass it not used during regular rendering.
+		Pass
+		{
+			Name "META" 
+			Tags { "LightMode"="Meta" }
+
+			Cull Off
+
+			CGPROGRAM
+			#pragma vertex vert_meta
+			#pragma fragment frag_meta
+
+			#pragma shader_feature _EMISSION
+			#pragma shader_feature _METALLICGLOSSMAP
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature ___ _DETAIL_MULX2
+
+			#include "UnityStandardMeta.cginc"
+			ENDCG
+		}
+	}
+
+	SubShader
+	{
+		Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
+		LOD 150
+
+		// ------------------------------------------------------------------
+		//  Base forward pass (directional light, emission, lightmaps, ...)
+		Pass
+		{
+			Name "FORWARD" 
+			Tags { "LightMode" = "ForwardBase" }
+
+			Blend [_SrcBlend] [_DstBlend]
+			ZWrite [_ZWrite]
+
+			CGPROGRAM
+			#pragma target 2.0
+			
+			#pragma shader_feature _NORMALMAP
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _EMISSION 
+			#pragma shader_feature _METALLICGLOSSMAP 
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
+			#pragma shader_feature _ _GLOSSYREFLECTIONS_OFF
+			// SM2.0: NOT SUPPORTED shader_feature ___ _DETAIL_MULX2
+			// SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP
+
+			#pragma skip_variants SHADOWS_SOFT DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
+
+			#pragma multi_compile_fwdbase
+			#pragma multi_compile_fog
+
+			#pragma vertex vertBase
+			#pragma fragment fragBase
+			#include "UnityStandardCoreForward.cginc"
+
+			ENDCG
+		}
+		// ------------------------------------------------------------------
+		//  Additive forward pass (one light per pass)
+		Pass
+		{
+			Name "FORWARD_DELTA"
+			Tags { "LightMode" = "ForwardAdd" }
+			Blend [_SrcBlend] One
+			Fog { Color (0,0,0,0) } // in additive pass fog should be black
+			ZWrite Off
+			ZTest LEqual
+			
+			CGPROGRAM
+			#pragma target 2.0
+
+			#pragma shader_feature _NORMALMAP
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _METALLICGLOSSMAP
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
+			#pragma shader_feature ___ _DETAIL_MULX2
+			// SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP
+			#pragma skip_variants SHADOWS_SOFT
+			
+			#pragma multi_compile_fwdadd_fullshadows
+			#pragma multi_compile_fog
+			
+			#pragma vertex vertAdd
+			#pragma fragment fragAdd
+			#include "UnityStandardCoreForward.cginc"
+
+			ENDCG
+		}
+		// ------------------------------------------------------------------
+		//  Shadow rendering pass
+		Pass {
+			Name "ShadowCaster"
+			Tags { "LightMode" = "ShadowCaster" }
+			
+			ZWrite On ZTest LEqual
+
+			CGPROGRAM
+			#pragma target 2.0
+
+			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
+			#pragma shader_feature _METALLICGLOSSMAP
+			#pragma skip_variants SHADOWS_SOFT
+			#pragma multi_compile_shadowcaster
+
+			#pragma vertex vertShadowCaster
+			#pragma fragment fragShadowCaster
+
+			#include "UnityStandardShadow.cginc"
+
+			ENDCG
+		}
+
+		// ------------------------------------------------------------------
+		// Extracts information for lightmapping, GI (emission, albedo, ...)
+		// This pass it not used during regular rendering.
+		Pass
+		{
+			Name "META" 
+			Tags { "LightMode"="Meta" }
+
+			Cull Off
+
+			CGPROGRAM
+			#pragma vertex vert_meta
+			#pragma fragment frag_meta
+
+			#pragma shader_feature _EMISSION
+			#pragma shader_feature _METALLICGLOSSMAP
+			#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+			#pragma shader_feature ___ _DETAIL_MULX2
+
+			#include "UnityStandardMeta.cginc"
+			ENDCG
+		}
+	}
+
+	Dependency "BabylonMaterial" = "Hidden/Babylon/Material"
+
+	FallBack "VertexLit"
+	CustomEditor "BabylonShaderInterface"
+}

+ 2 - 2
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/BabylonPhysicsState.cs

@@ -7,8 +7,8 @@ namespace UnityEditor
     public sealed class BabylonPhysicsState : MonoBehaviour
     {
         public float mass = 0.0f;
-        public float friction = 0.2f;
-        public float restitution = 0.2f;
+        public float friction = 0.1f;
+        public float restitution = 0.25f;
         public BabylonPhysicsImposter imposter = BabylonPhysicsImposter.None;
     }
 }

+ 480 - 0
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/BabylonShaderInterface.cs

@@ -0,0 +1,480 @@
+using System;
+using UnityEngine;
+
+namespace UnityEditor
+{
+	public class BabylonShaderInterface : ShaderGUI
+	{
+		private enum WorkflowMode
+		{
+			Specular,
+			Metallic,
+			Dielectric
+		}
+
+		public enum BlendMode
+		{
+			Opaque,
+			Cutout,
+			Fade,		// Old school alpha-blending mode, fresnel does not affect amount of transparency
+			Transparent // Physically plausible transparency mode, implemented as alpha pre-multiply
+		}
+
+		public enum SmoothnessMapChannel
+		{
+			SpecularMetallicAlpha,
+			AlbedoAlpha,
+		}
+
+		private static class Styles
+		{
+			public static GUIStyle optionsButton = "PaneOptions";
+			public static GUIContent uvSetLabel = new GUIContent("UV Set");
+			public static GUIContent[] uvSetOptions = new GUIContent[] { new GUIContent("UV channel 0"), new GUIContent("UV channel 1") };
+
+			public static string emptyTootip = "";
+			public static GUIContent albedoText = new GUIContent("Albedo", "Albedo (RGB) and Transparency (A)");
+			public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
+			public static GUIContent specularMapText = new GUIContent("Specular", "Specular (RGB) and Smoothness (A)");
+			public static GUIContent metallicMapText = new GUIContent("Metallic", "Metallic (R) and Smoothness (A)");
+			public static GUIContent smoothnessText = new GUIContent("Smoothness", "Smoothness value");
+			public static GUIContent smoothnessScaleText = new GUIContent("Smoothness", "Smoothness scale factor");
+			public static GUIContent smoothnessMapChannelText = new GUIContent("Source", "Smoothness texture and channel");
+			public static GUIContent highlightsText = new GUIContent("Specular Highlights", "Specular Highlights");
+			public static GUIContent reflectionsText = new GUIContent("Reflections", "Glossy Reflections");
+			public static GUIContent alphaModeText = new GUIContent("Alpha Blending Mode", "Alpha Blending Mode");
+			public static GUIContent disableLightingText = new GUIContent("Disable Surface Lighting", "Disable Surface Lighting");
+			public static GUIContent useEmissiveAsIlluminationText = new GUIContent("Use Emissive Illumination", "Use Emissive Illumination");
+			public static GUIContent roughnessText = new GUIContent("Roughness", "Roughness");
+			public static GUIContent useRoughnessAlphaText = new GUIContent("From Alpha", "From Alpha");
+			public static GUIContent useRoughnessGreenText = new GUIContent("From Green", "From Green");
+			public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map");
+			public static GUIContent heightMapText = new GUIContent("Height Map", "Height Map (G)");
+			public static GUIContent occlusionText = new GUIContent("Occlusion", "Occlusion (G)");
+			public static GUIContent emissionText = new GUIContent("Emission", "Emission (RGB)");
+			public static GUIContent detailMaskText = new GUIContent("Detail Mask", "Mask for Secondary Maps (A)");
+			public static GUIContent detailAlbedoText = new GUIContent("Detail Albedo x2", "Albedo (RGB) multiplied by 2");
+			public static GUIContent detailNormalMapText = new GUIContent("Normal Map", "Normal Map");
+
+			public static string whiteSpaceString = " ";
+			public static string primaryMapsText = "Main Maps";
+			public static string secondaryMapsText = "Secondary Maps";
+			public static string babylonText = "Babylon Rendering Options";
+			public static string forwardText = "Forward Rendering Options";
+			public static string renderingMode = "Rendering Mode";
+			public static GUIContent emissiveWarning = new GUIContent ("Emissive value is animated but the material has not been configured to support emissive. Please make sure the material itself has some amount of emissive.");
+			public static GUIContent emissiveColorWarning = new GUIContent ("Ensure emissive color is non-black for emission to have effect.");
+			public static readonly string[] blendNames = Enum.GetNames (typeof (BlendMode));
+		}
+
+		MaterialProperty blendMode = null;
+		MaterialProperty albedoMap = null;
+		MaterialProperty albedoColor = null;
+		MaterialProperty alphaCutoff = null;
+		MaterialProperty specularMap = null;
+		MaterialProperty specularColor = null;
+		MaterialProperty metallicMap = null;
+		MaterialProperty metallic = null;
+		MaterialProperty smoothness = null;
+		MaterialProperty smoothnessScale = null;
+		MaterialProperty smoothnessMapChannel = null;
+		MaterialProperty highlights = null;
+		MaterialProperty reflections = null;
+		MaterialProperty alphaMode = null;
+		MaterialProperty disableLighting = null;
+		MaterialProperty useEmissiveAsIllumination = null;
+		MaterialProperty roughness = null;
+		MaterialProperty useRoughnessAlpha = null;
+		MaterialProperty useRoughnessGreen = null;
+		MaterialProperty bumpScale = null;
+		MaterialProperty bumpMap = null;
+		MaterialProperty occlusionStrength = null;
+		MaterialProperty occlusionMap = null;
+		MaterialProperty heigtMapScale = null;
+		MaterialProperty heightMap = null;
+		MaterialProperty emissionColorForRendering = null;
+		MaterialProperty emissionMap = null;
+		MaterialProperty detailMask = null;
+		MaterialProperty detailAlbedoMap = null;
+		MaterialProperty detailNormalMapScale = null;
+		MaterialProperty detailNormalMap = null;
+		MaterialProperty uvSetSecondary = null;
+
+		MaterialEditor m_MaterialEditor;
+		WorkflowMode m_WorkflowMode = WorkflowMode.Specular;
+		ColorPickerHDRConfig m_ColorPickerHDRConfig = new ColorPickerHDRConfig(0f, 99f, 1/99f, 3f);
+
+		bool m_FirstTimeApply = true;
+
+		public void FindProperties (MaterialProperty[] props)
+		{
+			blendMode = FindProperty ("_Mode", props);
+			albedoMap = FindProperty ("_MainTex", props);
+			albedoColor = FindProperty ("_Color", props);
+			alphaCutoff = FindProperty ("_Cutoff", props);
+			specularMap = FindProperty ("_SpecGlossMap", props, false);
+			specularColor = FindProperty ("_SpecColor", props, false);
+			metallicMap = FindProperty ("_MetallicGlossMap", props, false);
+			metallic = FindProperty ("_Metallic", props, false);
+			if (specularMap != null && specularColor != null)
+				m_WorkflowMode = WorkflowMode.Specular;
+			else if (metallicMap != null && metallic != null)
+				m_WorkflowMode = WorkflowMode.Metallic;
+			else
+				m_WorkflowMode = WorkflowMode.Dielectric;
+			smoothness = FindProperty ("_Glossiness", props);
+			smoothnessScale = FindProperty ("_GlossMapScale", props, false);
+			smoothnessMapChannel = FindProperty ("_SmoothnessTextureChannel", props, false);
+			highlights = FindProperty ("_SpecularHighlights", props, false);
+			reflections = FindProperty ("_GlossyReflections", props, false);
+			disableLighting = FindProperty ("_DisableLighting", props, false);
+			useEmissiveAsIllumination = FindProperty ("_UseEmissiveAsIllumination", props, false);
+			roughness = FindProperty ("_Roughness", props, false);
+			useRoughnessAlpha = FindProperty ("_UseRoughnessFromMetallicTextureAlpha", props, false);
+			useRoughnessGreen = FindProperty ("_UseRoughnessFromMetallicTextureGreen", props, false);
+			bumpScale = FindProperty ("_BumpScale", props);
+			bumpMap = FindProperty ("_BumpMap", props);
+			heigtMapScale = FindProperty ("_Parallax", props);
+			heightMap = FindProperty("_ParallaxMap", props);
+			occlusionStrength = FindProperty ("_OcclusionStrength", props);
+			occlusionMap = FindProperty ("_OcclusionMap", props);
+			emissionColorForRendering = FindProperty ("_EmissionColor", props);
+			emissionMap = FindProperty ("_EmissionMap", props);
+			detailMask = FindProperty ("_DetailMask", props);
+			detailAlbedoMap = FindProperty ("_DetailAlbedoMap", props);
+			detailNormalMapScale = FindProperty ("_DetailNormalMapScale", props);
+			detailNormalMap = FindProperty ("_DetailNormalMap", props);
+			uvSetSecondary = FindProperty ("_UVSec", props);
+			alphaMode = FindProperty ("_AlphaMode", props);
+		}
+
+		public override void OnGUI (MaterialEditor materialEditor, MaterialProperty[] props)
+		{
+			FindProperties (props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
+			m_MaterialEditor = materialEditor;
+			Material material = materialEditor.target as Material;
+
+			// Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing
+			// material to a standard shader.
+			// Do this before any GUI code has been issued to prevent layout issues in subsequent GUILayout statements (case 780071)
+			if (m_FirstTimeApply)
+			{
+				MaterialChanged(material, m_WorkflowMode);
+				m_FirstTimeApply = false;
+			}
+
+			ShaderPropertiesGUI (material);
+		}
+
+		public void ShaderPropertiesGUI (Material material)
+		{
+			// Use default labelWidth
+			EditorGUIUtility.labelWidth = 0f;
+
+			// Detect any changes to the material
+			EditorGUI.BeginChangeCheck();
+			{
+				BlendModePopup();
+
+				// Primary properties
+				GUILayout.Label (Styles.primaryMapsText, EditorStyles.boldLabel);
+				DoAlbedoArea(material);
+				DoSpecularMetallicArea();
+
+				m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null);
+				m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null);
+				m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null);
+				DoEmissionArea(material);
+				m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask);
+				EditorGUI.BeginChangeCheck();
+				m_MaterialEditor.TextureScaleOffsetProperty(albedoMap);
+				if (EditorGUI.EndChangeCheck())
+					emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake
+
+				EditorGUILayout.Space();
+
+				// Secondary properties
+				GUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel);
+				m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap);
+				m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale);
+				m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap);
+				m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text);
+
+				// Third properties
+				GUILayout.Label(Styles.babylonText, EditorStyles.boldLabel);
+				if (alphaMode != null)
+					m_MaterialEditor.ShaderProperty(alphaMode, Styles.alphaModeText);
+				if (disableLighting != null)
+					m_MaterialEditor.ShaderProperty(disableLighting, Styles.disableLightingText);
+				if (useEmissiveAsIllumination != null)
+					m_MaterialEditor.ShaderProperty(useEmissiveAsIllumination, Styles.useEmissiveAsIlluminationText);
+
+				// Forth properties
+				GUILayout.Label(Styles.forwardText, EditorStyles.boldLabel);
+				if (highlights != null)
+					m_MaterialEditor.ShaderProperty(highlights, Styles.highlightsText);
+				if (reflections != null)
+					m_MaterialEditor.ShaderProperty(reflections, Styles.reflectionsText);
+			}
+			if (EditorGUI.EndChangeCheck())
+			{
+				foreach (var obj in blendMode.targets)
+					MaterialChanged((Material)obj, m_WorkflowMode);
+			}
+		}
+
+		internal void DetermineWorkflow(MaterialProperty[] props)
+		{
+			if (FindProperty("_SpecGlossMap", props, false) != null && FindProperty("_SpecColor", props, false) != null)
+				m_WorkflowMode = WorkflowMode.Specular;
+			else if (FindProperty("_MetallicGlossMap", props, false) != null && FindProperty("_Metallic", props, false) != null)
+				m_WorkflowMode = WorkflowMode.Metallic;
+			else
+				m_WorkflowMode = WorkflowMode.Dielectric;
+		}
+
+		public override void AssignNewShaderToMaterial (Material material, Shader oldShader, Shader newShader)
+		{
+			// _Emission property is lost after assigning Standard shader to the material
+			// thus transfer it before assigning the new shader
+			if (material.HasProperty("_Emission"))
+			{
+				material.SetColor("_EmissionColor", material.GetColor("_Emission"));
+			}
+
+			base.AssignNewShaderToMaterial(material, oldShader, newShader);
+
+			if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/"))
+			{
+				SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));
+				return;
+			}
+
+			BlendMode blendMode = BlendMode.Opaque;
+			if (oldShader.name.Contains("/Transparent/Cutout/"))
+			{
+				blendMode = BlendMode.Cutout;
+			}
+			else if (oldShader.name.Contains("/Transparent/"))
+			{
+				// NOTE: legacy shaders did not provide physically based transparency
+				// therefore Fade mode
+				blendMode = BlendMode.Fade;
+			}
+			material.SetFloat("_Mode", (float)blendMode);
+
+			DetermineWorkflow( MaterialEditor.GetMaterialProperties (new Material[] { material }) );
+			MaterialChanged(material, m_WorkflowMode);
+		}
+
+		void BlendModePopup()
+		{
+			EditorGUI.showMixedValue = blendMode.hasMixedValue;
+			var mode = (BlendMode)blendMode.floatValue;
+
+			EditorGUI.BeginChangeCheck();
+			mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);
+			if (EditorGUI.EndChangeCheck())
+			{
+				m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode");
+				blendMode.floatValue = (float)mode;
+			}
+
+			EditorGUI.showMixedValue = false;
+		}
+
+		void DoAlbedoArea(Material material)
+		{
+			m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);
+			if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Cutout))
+			{
+				m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel+1);
+			}
+		}
+
+		void DoEmissionArea(Material material)
+		{
+			bool showHelpBox = !HasValidEmissiveKeyword(material);
+			
+			bool hadEmissionTexture = emissionMap.textureValue != null;
+
+			// Texture and HDR color controls
+			m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, m_ColorPickerHDRConfig, false);
+
+			// If texture was assigned and color was black set color to white
+			float brightness = emissionColorForRendering.colorValue.maxColorComponent;
+			if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f)
+				emissionColorForRendering.colorValue = Color.white;
+
+			// Emission for GI?
+			m_MaterialEditor.LightmapEmissionProperty (MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
+			
+			if (showHelpBox)
+			{
+				EditorGUILayout.HelpBox(Styles.emissiveWarning.text, MessageType.Warning);
+			}
+		}
+
+		void DoSpecularMetallicArea()
+		{
+			bool hasGlossMap = false;
+			if (m_WorkflowMode == WorkflowMode.Specular)
+			{
+				hasGlossMap = specularMap.textureValue != null;
+				m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap, hasGlossMap ? null : specularColor);
+			}
+			else if (m_WorkflowMode == WorkflowMode.Metallic)
+			{
+				hasGlossMap = metallicMap.textureValue != null;
+				m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap, hasGlossMap ? null : metallic);
+			}
+
+			bool showSmoothnessScale = hasGlossMap;
+			if (smoothnessMapChannel != null)
+			{
+				int smoothnessChannel = (int) smoothnessMapChannel.floatValue;
+				if (smoothnessChannel == (int) SmoothnessMapChannel.AlbedoAlpha)
+					showSmoothnessScale = true;
+			}
+
+			int indentation = 2; // align with labels of texture properties
+
+			// Roughness properties
+			if (roughness != null)
+				m_MaterialEditor.ShaderProperty(roughness, Styles.roughnessText, indentation);
+			if (useRoughnessAlpha != null)
+				m_MaterialEditor.ShaderProperty(useRoughnessAlpha, Styles.useRoughnessAlphaText, indentation);
+			if (useRoughnessGreen != null)
+				m_MaterialEditor.ShaderProperty(useRoughnessGreen, Styles.useRoughnessGreenText, indentation);
+			if (roughness != null || useRoughnessAlpha != null || useRoughnessGreen != null)
+  				EditorGUILayout.Space();
+
+			m_MaterialEditor.ShaderProperty(showSmoothnessScale ? smoothnessScale : smoothness, showSmoothnessScale ? Styles.smoothnessScaleText : Styles.smoothnessText, indentation);
+		
+			++indentation;
+			if (smoothnessMapChannel != null)
+				m_MaterialEditor.ShaderProperty(smoothnessMapChannel, Styles.smoothnessMapChannelText, indentation);
+		}
+
+		public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode)
+		{
+			switch (blendMode)
+			{
+				case BlendMode.Opaque:
+					material.SetOverrideTag("RenderType", "");
+					material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
+					material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
+					material.SetInt("_ZWrite", 1);
+					material.DisableKeyword("_ALPHATEST_ON");
+					material.DisableKeyword("_ALPHABLEND_ON");
+					material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
+					material.renderQueue = -1;
+					break;
+				case BlendMode.Cutout:
+					material.SetOverrideTag("RenderType", "TransparentCutout");
+					material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
+					material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
+					material.SetInt("_ZWrite", 1);
+					material.EnableKeyword("_ALPHATEST_ON");
+					material.DisableKeyword("_ALPHABLEND_ON");
+					material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
+					material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;
+					break;
+				case BlendMode.Fade:
+					material.SetOverrideTag("RenderType", "Transparent");
+					material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
+					material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
+					material.SetInt("_ZWrite", 0);
+					material.DisableKeyword("_ALPHATEST_ON");
+					material.EnableKeyword("_ALPHABLEND_ON");
+					material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
+					material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
+					break;
+				case BlendMode.Transparent:
+					material.SetOverrideTag("RenderType", "Transparent");
+					material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
+					material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
+					material.SetInt("_ZWrite", 0);
+					material.DisableKeyword("_ALPHATEST_ON");
+					material.DisableKeyword("_ALPHABLEND_ON");
+					material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
+					material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
+					break;
+			}
+		}
+
+		static SmoothnessMapChannel GetSmoothnessMapChannel(Material material)
+		{
+			int ch = (int) material.GetFloat("_SmoothnessTextureChannel");
+			if (ch == (int) SmoothnessMapChannel.AlbedoAlpha)
+				return SmoothnessMapChannel.AlbedoAlpha;
+			else
+				return SmoothnessMapChannel.SpecularMetallicAlpha;
+		}
+
+		static bool ShouldEmissionBeEnabled(Material mat, Color color)
+		{
+			var realtimeEmission = (mat.globalIlluminationFlags & MaterialGlobalIlluminationFlags.RealtimeEmissive) > 0;
+			return color.maxColorComponent > 0.1f / 255.0f || realtimeEmission;
+		}
+
+		static void SetMaterialKeywords(Material material, WorkflowMode workflowMode)
+		{
+			// Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
+			// (MaterialProperty value might come from renderer material property block)
+			SetKeyword (material, "_NORMALMAP", material.GetTexture ("_BumpMap") || material.GetTexture ("_DetailNormalMap"));
+			if (workflowMode == WorkflowMode.Specular)
+				SetKeyword (material, "_SPECGLOSSMAP", material.GetTexture ("_SpecGlossMap"));
+			else if (workflowMode == WorkflowMode.Metallic)
+				SetKeyword (material, "_METALLICGLOSSMAP", material.GetTexture ("_MetallicGlossMap"));
+			SetKeyword (material, "_PARALLAXMAP", material.GetTexture ("_ParallaxMap"));
+			SetKeyword (material, "_DETAIL_MULX2", material.GetTexture ("_DetailAlbedoMap") || material.GetTexture ("_DetailNormalMap"));
+
+			bool shouldEmissionBeEnabled = ShouldEmissionBeEnabled (material, material.GetColor("_EmissionColor"));
+			SetKeyword (material, "_EMISSION", shouldEmissionBeEnabled);
+
+			if (material.HasProperty("_SmoothnessTextureChannel"))
+			{
+				SetKeyword (material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A", GetSmoothnessMapChannel(material) == SmoothnessMapChannel.AlbedoAlpha);
+			}
+
+			// Setup lightmap emissive flags
+			MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
+			if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0)
+			{
+				flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
+				if (!shouldEmissionBeEnabled)
+					flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
+
+				material.globalIlluminationFlags = flags;
+			}
+		}
+
+		bool HasValidEmissiveKeyword (Material material)
+		{
+			// Material animation might be out of sync with the material keyword.
+			// So if the emission support is disabled on the material, but the property blocks have a value that requires it, then we need to show a warning.
+			// (note: (Renderer MaterialPropertyBlock applies its values to emissionColorForRendering))
+			bool hasEmissionKeyword = material.IsKeywordEnabled ("_EMISSION");
+			if (!hasEmissionKeyword && ShouldEmissionBeEnabled (material, emissionColorForRendering.colorValue))
+				return false;
+			else
+				return true;
+		}
+
+		static void MaterialChanged(Material material, WorkflowMode workflowMode)
+		{
+			SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));
+
+			SetMaterialKeywords(material, workflowMode);
+		}
+
+		static void SetKeyword(Material m, string keyword, bool state)
+		{
+			if (state)
+				m.EnableKeyword (keyword);
+			else
+				m.DisableKeyword (keyword);
+		}
+	}
+} // namespace UnityEditor

+ 3 - 5
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/ExportationOptions.cs

@@ -22,12 +22,11 @@ namespace Unity3D2Babylon
         public bool ExportPhysics { get; set; }
         public bool ExportShadows { get; set; }
         public bool WorkerCollisions { get; set; }
-        public SerializableVector3 Gravity { get; set; }
-        public SerializableVector3 CameraEllipsoid { get; set; }
         public int ShadowMapSize { get; set; }
         public float ShadowMapBias { get; set; }
         public float ShadowBlurScale { get; set; }
         public float ProductionVersion { get; set; }
+        public float DefaultAspectRatio { get; set; }
         public int DefaultUpdateOptions { get; set; }
         public int DefaultPreviewWindow { get; set; }
         public int DefaultLightFilter { get; set; }
@@ -65,15 +64,14 @@ namespace Unity3D2Babylon
             ExportPhysics = true;
             ExportShadows = false;
             WorkerCollisions = false;
-            Gravity = new Vector3(0, -0.9f, 0);
-            CameraEllipsoid = new Vector3(0.5f, 0.85f, 0.5f);
             ShadowMapSize = 1024;
             ShadowMapBias = 0.0001f;
             ShadowBlurScale = 0;
+            DefaultAspectRatio = 1f;
             DefaultUpdateOptions = 0;
             DefaultPreviewWindow = 0;
             DefaultLightFilter = 4;
-            DefaultImageFormat = 0;
+            DefaultImageFormat = 1;
             DefaultLightmapMode = 0;
             DefaultLightmapBaking = 0;
             DefaultCoordinatesIndex = 1;

+ 2 - 0
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/ExporterMetadata.cs

@@ -245,6 +245,8 @@ namespace UnityEditor
     {
         public bool autoClear = true;
         public Color ambientColor = Color.clear;
+        public Vector3 defaultGravity = new Vector3(0, -0.9f, 0);
+        public Vector3 cameraEllipsoid = new Vector3(0.5f, 0.85f, 0.5f);
         public BabylonNavigationMesh navigationMesh = BabylonNavigationMesh.EnableNavigation;
         public bool particleSystems = true;
         public bool lensFlareSystems = true;

+ 16 - 22
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/ExporterWindow.cs

@@ -88,6 +88,8 @@ namespace Unity3D2Babylon
         [MenuItem("BabylonJS/Update Libraries", false, 2)]
         public static void InitUpdate()
         {
+            Tools.EnableRemoteCertificates();
+            
             string prodVersion = ExporterWindow.exportationOptions.ProductionVersion.ToString();
             if (prodVersion.IndexOf(".", StringComparison.OrdinalIgnoreCase) < 0)
             {
@@ -467,42 +469,34 @@ namespace Unity3D2Babylon
             EditorGUILayout.Space();
             exportationOptions.LightIntensityFactor = EditorGUILayout.Slider(" Light Intensity Factor", exportationOptions.LightIntensityFactor, 0, 10.0f);
             EditorGUILayout.Space();
-            exportationOptions.ReflectionDefaultLevel = EditorGUILayout.Slider(" Default Reflection Level", exportationOptions.ReflectionDefaultLevel, 0, 1.0f);
+            exportationOptions.DefaultAspectRatio = EditorGUILayout.Slider(" Viewport Camera Ratio", exportationOptions.DefaultAspectRatio, 0, 10.0f);
             EditorGUILayout.Space();
-            exportationOptions.DefaultImageFormat = (int)(BabylonImageFormat)EditorGUILayout.EnumPopup(" Prefered Texture Format", (BabylonImageFormat)exportationOptions.DefaultImageFormat, GUILayout.ExpandWidth(true));
+            exportationOptions.ReflectionDefaultLevel = EditorGUILayout.Slider(" Default Reflection Level", exportationOptions.ReflectionDefaultLevel, 0, 1.0f);
             EditorGUILayout.Space();
             exportationOptions.DefaultQualityLevel = (int)EditorGUILayout.Slider(" Texture Image Quality", exportationOptions.DefaultQualityLevel, 0, 100);
             EditorGUILayout.Space();
+            exportationOptions.DefaultImageFormat = (int)(BabylonImageFormat)EditorGUILayout.EnumPopup(" Prefered Texture Format", (BabylonImageFormat)exportationOptions.DefaultImageFormat, GUILayout.ExpandWidth(true));
+            EditorGUILayout.Space();
 
-            showCollision = EditorGUILayout.Foldout(showCollision, "Scene Collision Options");
-            if (showCollision)
+            showShader = EditorGUILayout.Foldout(showShader, "Shader Program Options");
+            if (showShader)
             {
                 EditorGUILayout.Space();
-                exportationOptions.ExportCollisions = EditorGUILayout.Toggle("   Enable Collisions", exportationOptions.ExportCollisions);
-                EditorGUILayout.Space();
-                EditorGUILayout.BeginHorizontal();
-                GUILayout.Label("   Camera Ellipsoid");
-                exportationOptions.CameraEllipsoid = EditorGUILayout.Vector3Field("", exportationOptions.CameraEllipsoid, GUILayout.ExpandWidth(false));
-                EditorGUILayout.EndHorizontal();
-                EditorGUILayout.Space();
-                EditorGUILayout.BeginHorizontal();
-                GUILayout.Label("   Default Scene Gravity");
-                exportationOptions.Gravity = EditorGUILayout.Vector3Field("", exportationOptions.Gravity, GUILayout.ExpandWidth(false));
-                EditorGUILayout.EndHorizontal();
-                EditorGUILayout.Space();
-                exportationOptions.DefaultColliderDetail = (int)(BabylonColliderDetail)EditorGUILayout.EnumPopup("   Default Collider Detail", (BabylonColliderDetail)exportationOptions.DefaultColliderDetail, GUILayout.ExpandWidth(true));
+                exportationOptions.EmbeddedShaders = EditorGUILayout.Toggle("   Embed Shader Files", exportationOptions.EmbeddedShaders);
                 EditorGUILayout.Space();
-                exportationOptions.WorkerCollisions = EditorGUILayout.Toggle("   Enable Worker Collisions", exportationOptions.WorkerCollisions);
+                exportationOptions.DefaultShaderFolder = EditorGUILayout.TextField("   Output Src Shader Path", exportationOptions.DefaultShaderFolder);
                 EditorGUILayout.Space();
             }
 
-            showShader = EditorGUILayout.Foldout(showShader, "Shader Program Options");
-            if (showShader)
+            showCollision = EditorGUILayout.Foldout(showCollision, "Collision Engine Options");
+            if (showCollision)
             {
                 EditorGUILayout.Space();
-                exportationOptions.EmbeddedShaders = EditorGUILayout.Toggle("   Embed Shader Files", exportationOptions.EmbeddedShaders);
+                exportationOptions.ExportCollisions = EditorGUILayout.Toggle("   Enable Collisions", exportationOptions.ExportCollisions);
                 EditorGUILayout.Space();
-                exportationOptions.DefaultShaderFolder = EditorGUILayout.TextField("   Output Src Shader Path", exportationOptions.DefaultShaderFolder);
+                exportationOptions.WorkerCollisions = EditorGUILayout.Toggle("   Use Worker Threads", exportationOptions.WorkerCollisions);
+                EditorGUILayout.Space();
+                exportationOptions.DefaultColliderDetail = (int)(BabylonColliderDetail)EditorGUILayout.EnumPopup("   Default Collider Detail", (BabylonColliderDetail)exportationOptions.DefaultColliderDetail, GUILayout.ExpandWidth(true));
                 EditorGUILayout.Space();
             }
 

+ 11 - 7
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/SceneBuilder.Cameras.cs

@@ -28,6 +28,7 @@ namespace Unity3D2Babylon
             metaData.properties.Add("clearFlags", camera.clearFlags.ToString());
             metaData.properties.Add("cullingMask", camera.cullingMask);
             metaData.properties.Add("stereoEnabled", camera.stereoEnabled);
+            metaData.properties.Add("isOrthographic", camera.orthographic);
             metaData.properties.Add("useOcclusionCulling", camera.useOcclusionCulling);
             babylonCamera.tags = componentTags;
 
@@ -37,11 +38,12 @@ namespace Unity3D2Babylon
             babylonCamera.isStereoscopicSideBySide = camera.stereoEnabled;
             if (camera.orthographic)
             {
-                float size = camera.orthographicSize;
-                babylonCamera.orthoTop = size;
-                babylonCamera.orthoBottom = -size;
-                babylonCamera.orthoLeft = -size;
-                babylonCamera.orthoRight = size;
+                float vert = camera.orthographicSize;
+                float horz = vert * exportationOptions.DefaultAspectRatio;
+                babylonCamera.orthoTop = vert;
+                babylonCamera.orthoBottom = -vert;
+                babylonCamera.orthoLeft = -horz;
+                babylonCamera.orthoRight = horz;
                 babylonCamera.mode = 1;
             }
             else
@@ -65,8 +67,10 @@ namespace Unity3D2Babylon
             if (exportationOptions.ExportCollisions)
             {
                 babylonCamera.checkCollisions = true;
-                babylonCamera.applyGravity = (exportationOptions.Gravity.X == 0 && exportationOptions.Gravity.Y == 0 && exportationOptions.Gravity.Z == 0) ? false : true;
-                babylonCamera.ellipsoid = exportationOptions.CameraEllipsoid.ToFloat();
+                if (SceneController != null) {
+                    babylonCamera.applyGravity = (SceneController.sceneOptions.defaultGravity.y == 0 && SceneController.sceneOptions.defaultGravity.y == 0 && SceneController.sceneOptions.defaultGravity.z == 0) ? false : true;
+                    babylonCamera.ellipsoid = SceneController.sceneOptions.cameraEllipsoid.ToFloat();
+                }
             }
 
             // Lens Flares

+ 101 - 21
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/SceneBuilder.Materials.cs

@@ -299,15 +299,19 @@ namespace Unity3D2Babylon
 
         private BabylonMaterial DumpMaterial(Material material, int lightmapIndex = -1, Vector4 lightmapScaleOffset = default(Vector4), int lightmapCoordIndex = -1)
         {
-            if (material.shader.name == "Standard")
+            if (material.shader.name == "Standard" || material.shader.name == "BabylonJS/Materials/PBR Material")
             {
                 return DumpPBRMaterial(material, lightmapIndex, lightmapScaleOffset, true, lightmapCoordIndex);
             }
-            else if (material.shader.name == "Standard (Specular setup)")
+            else if (material.shader.name == "Standard (Specular setup)" || material.shader.name == "BabylonJS/Materials/PBR Material (Specular)")
             {
                 return DumpPBRMaterial(material, lightmapIndex, lightmapScaleOffset, false, lightmapCoordIndex);
             }
-            else if (material.shader.name.Substring(0, 10) == "BabylonJS/")
+            else if (material.shader.name.StartsWith("BabylonJS/Materials/", StringComparison.OrdinalIgnoreCase))
+            {
+                return DumpStandardMaterial(material, lightmapIndex, lightmapScaleOffset, lightmapCoordIndex);
+            }
+            else if (material.shader.name.StartsWith("BabylonJS/", StringComparison.OrdinalIgnoreCase))
             {
                 return DumpShaderMaterial(material);
             }
@@ -328,11 +332,6 @@ namespace Unity3D2Babylon
                 };
 
                 ExporterWindow.ReportProgress(1, "Exporting standard material: " + material.name);
-                if (exportationOptions.DefaultLightmapMode == (int)BabylonLightmapMode.FullLightBaking)
-                {
-                    bMat.disableLighting = true;
-                    bMat.useEmissiveAsIllumination = true;
-                }
 
                 // Default diffuse
                 bMat.diffuse[0] = 1.0f;
@@ -379,6 +378,27 @@ namespace Unity3D2Babylon
                         UnityEngine.Debug.LogWarning("Material Emission Is Float Not Color: " + material.name);
                     }
                 }
+
+                if (material.HasProperty("_AlphaMode"))
+                {
+                    bMat.alphaMode = material.GetInt("_AlphaMode");
+                }
+
+                if (material.HasProperty("_DisableLighting"))
+                {
+                    bMat.disableLighting = (material.GetInt("_DisableLighting") != 0);
+                }
+                
+                if (material.HasProperty("_UseEmissiveAsIllumination"))
+                {
+                    bMat.useEmissiveAsIllumination = (material.GetInt("_UseEmissiveAsIllumination") != 0);
+                }
+
+                if (material.HasProperty("_BackFaceCulling"))
+                {
+                    bMat.backFaceCulling = (material.GetInt("_BackFaceCulling") != 0);
+                }
+
                 if (material.mainTexture && !materialNotSupported)
                 {
                     var mainTexture2D = material.mainTexture as Texture2D;
@@ -414,6 +434,13 @@ namespace Unity3D2Babylon
                 bMat.ambientTexture = DumpTextureFromMaterial(material, "_LightMap");
                 bMat.reflectionTexture = DumpTextureFromMaterial(material, "_Cube");
 
+                // Baking override
+                if (exportationOptions.DefaultLightmapMode == (int)BabylonLightmapMode.FullLightBaking)
+                {
+                    bMat.disableLighting = true;
+                    bMat.useEmissiveAsIllumination = true;
+                }
+
                 // If no ambient texture already (ambientTexture manually set for lightmaps on standard material)
                 bool hasLightmap = (exportationOptions.ExportLightmaps && lightmapIndex >= 0 && lightmapIndex != 65535 && LightmapSettings.lightmaps.Length > lightmapIndex);
                 if (hasLightmap && bMat.ambientTexture == null)
@@ -460,11 +487,6 @@ namespace Unity3D2Babylon
 
             ExporterWindow.ReportProgress(1, "Exporting physical material: " + material.name);
             babylonPbrMaterial.environmentIntensity = RenderSettings.ambientIntensity;
-            if (exportationOptions.DefaultLightmapMode == (int)BabylonLightmapMode.FullLightBaking)
-            {
-                babylonPbrMaterial.disableLighting = true;
-                babylonPbrMaterial.useEmissiveAsIllumination = true;
-            }
 
             if (material.mainTexture && material.mainTexture.GetType().FullName == "UnityEngine.ProceduralTexture")
             {
@@ -472,6 +494,41 @@ namespace Unity3D2Babylon
                 Debug.LogWarning("ProceduralTexture: " + material.mainTexture.name + " not supported by Babylon.js");
             }
 
+            if (material.HasProperty("_Roughness"))
+            {
+                babylonPbrMaterial.roughness = material.GetInt("_Roughness");
+            }
+
+            if (material.HasProperty("_UseRoughnessFromMetallicTextureAlpha"))
+            {
+                babylonPbrMaterial.useRoughnessFromMetallicTextureAlpha = (material.GetInt("_UseRoughnessFromMetallicTextureAlpha") != 0);
+            }
+
+            if (material.HasProperty("_UseRoughnessFromMetallicTextureGreen"))
+            {
+                babylonPbrMaterial.useRoughnessFromMetallicTextureGreen = (material.GetInt("_UseRoughnessFromMetallicTextureGreen") != 0);
+            }
+
+            if (material.HasProperty("_AlphaMode"))
+            {
+                babylonPbrMaterial.alphaMode = material.GetInt("_AlphaMode");
+            }
+
+            if (material.HasProperty("_DisableLighting"))
+            {
+                babylonPbrMaterial.disableLighting = (material.GetInt("_DisableLighting") != 0);
+            }
+            
+            if (material.HasProperty("_UseEmissiveAsIllumination"))
+            {
+                babylonPbrMaterial.useEmissiveAsIllumination = (material.GetInt("_UseEmissiveAsIllumination") != 0);
+            }
+
+            if (material.HasProperty("_BackFaceCulling"))
+            {
+                babylonPbrMaterial.backFaceCulling = (material.GetInt("_BackFaceCulling") != 0);
+            }
+
             // Albedo
             if (material.HasProperty("_Color"))
             {
@@ -517,6 +574,13 @@ namespace Unity3D2Babylon
             // Reflection
             babylonPbrMaterial.reflectionTexture = DumpReflectionTexture();
 
+            // Baking Override
+            if (exportationOptions.DefaultLightmapMode == (int)BabylonLightmapMode.FullLightBaking)
+            {
+                babylonPbrMaterial.disableLighting = true;
+                babylonPbrMaterial.useEmissiveAsIllumination = true;
+            }
+
             // Lightmapping
             bool hasLightmap = (exportationOptions.ExportLightmaps && lightmapIndex >= 0 && lightmapIndex != 65535 && LightmapSettings.lightmaps.Length > lightmapIndex);
             if (hasLightmap && babylonPbrMaterial.ambientTexture == null)
@@ -712,7 +776,7 @@ namespace Unity3D2Babylon
                     string[] attributes = babylonLine.Split(':');
                     if (attributes != null && attributes.Length > 1)
                     {
-                        string abuffer = attributes[1].Replace("[", "").Replace("]", "");
+                        string abuffer = attributes[1].Replace("[", "").Replace("]", "").Replace("\"", "");
                         if (!String.IsNullOrEmpty(abuffer))
                         {
                             abuffer = abuffer.Trim();
@@ -721,7 +785,7 @@ namespace Unity3D2Babylon
                             {
                                 foreach (string aoption in adata)
                                 {
-                                    string aoption_buffer = aoption.Trim().Replace("\"", "").Trim();
+                                    string aoption_buffer = aoption.Trim();
                                     if (!String.IsNullOrEmpty(aoption_buffer))
                                     {
                                         attributeList.Add(aoption_buffer);
@@ -736,7 +800,7 @@ namespace Unity3D2Babylon
                     string[] uniforms = babylonLine.Split(':');
                     if (uniforms != null && uniforms.Length > 1)
                     {
-                        string ubuffer = uniforms[1].Replace("[", "").Replace("]", "");
+                        string ubuffer = uniforms[1].Replace("[", "").Replace("]", "").Replace("\"", "");
                         if (!String.IsNullOrEmpty(ubuffer))
                         {
                             ubuffer = ubuffer.Trim();
@@ -745,7 +809,7 @@ namespace Unity3D2Babylon
                             {
                                 foreach (string uoption in udata)
                                 {
-                                    string uoption_buffer = uoption.Trim().Replace("\"", "").Trim();
+                                    string uoption_buffer = uoption.Trim();
                                     if (!String.IsNullOrEmpty(uoption_buffer))
                                     {
                                         uniformList.Add(uoption_buffer);
@@ -760,7 +824,7 @@ namespace Unity3D2Babylon
                     string[] samplers = babylonLine.Split(':');
                     if (samplers != null && samplers.Length > 1)
                     {
-                        string sbuffer = samplers[1].Replace("[", "").Replace("]", "");
+                        string sbuffer = samplers[1].Replace("[", "").Replace("]", "").Replace("\"", "");
                         if (!String.IsNullOrEmpty(sbuffer))
                         {
                             sbuffer = sbuffer.Trim();
@@ -769,7 +833,7 @@ namespace Unity3D2Babylon
                             {
                                 foreach (string soption in sdata)
                                 {
-                                    string soption_buffer = soption.Trim().Replace("\"", "").Trim();
+                                    string soption_buffer = soption.Trim();
                                     if (!String.IsNullOrEmpty(soption_buffer))
                                     {
                                         samplerList.Add(soption_buffer);
@@ -784,7 +848,7 @@ namespace Unity3D2Babylon
                     string[] defines = babylonLine.Split(':');
                     if (defines != null && defines.Length > 1)
                     {
-                        string dbuffer = defines[1].Replace("[", "").Replace("]", "");
+                        string dbuffer = defines[1].Replace("[", "").Replace("]", "").Replace("\"", "");
                         if (!String.IsNullOrEmpty(dbuffer))
                         {
                             dbuffer = dbuffer.Trim();
@@ -793,7 +857,7 @@ namespace Unity3D2Babylon
                             {
                                 foreach (string doption in ddata)
                                 {
-                                    string doption_buffer = doption.Trim().Replace("\"", "").Trim();
+                                    string doption_buffer = doption.Trim();
                                     if (!String.IsNullOrEmpty(doption_buffer))
                                     {
                                         defineList.Add(doption_buffer);
@@ -805,7 +869,23 @@ namespace Unity3D2Babylon
                 }
             }
 
+            if (material.HasProperty("_AlphaMode")) {
+                babylonShaderMaterial.alphaMode = material.GetInt("_AlphaMode");
+            }
+            bool needsAlphaBlending = false;
+            if (material.HasProperty("_NeedsAlphaBlending")) {
+                needsAlphaBlending = (material.GetInt("_NeedsAlphaBlending") != 0);
+            }
+            bool needsAlphaTesting = false;
+            if (material.HasProperty("_NeedsAlphaTesting")) {
+                needsAlphaTesting = (material.GetInt("_NeedsAlphaTesting") != 0);
+            }
+            if (material.HasProperty("_BackFaceCulling")) {
+                babylonShaderMaterial.backFaceCulling = (material.GetInt("_BackFaceCulling") != 0);
+            }
             babylonShaderMaterial.options = new BabylonShaderOptions();
+            babylonShaderMaterial.options.needAlphaBlending = needsAlphaBlending;
+            babylonShaderMaterial.options.needAlphaTesting = needsAlphaTesting;
             babylonShaderMaterial.options.attributes = attributeList.ToArray();
             babylonShaderMaterial.options.uniforms = uniformList.ToArray();
             babylonShaderMaterial.options.samplers = samplerList.ToArray();

+ 14 - 13
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/SceneBuilder.cs

@@ -395,7 +395,6 @@ namespace Unity3D2Babylon
                                 collisionMesh = new BabylonMesh();
                                 collisionMesh.tags = "[MESHCOLLIDER]";
                                 // Generate Mesh Collider Geometry
-                               
                                 if(!meshCollider.sharedMesh)
                                 {
                                     UnityEngine.Debug.LogWarning(meshCollider.gameObject+" has a Mesh Collider component without a mesh");
@@ -404,8 +403,6 @@ namespace Unity3D2Babylon
                                 {
                                     Tools.GenerateBabylonMeshData(meshCollider.sharedMesh, collisionMesh);
                                 }
-
-                            
                                 collisionMesh.position = Vector3.zero.ToFloat();
                                 collisionMesh.rotation = Vector3.zero.ToFloat();
                                 float factorX = 1f, factorY = 1f, factorZ = 1f;
@@ -656,15 +653,19 @@ namespace Unity3D2Babylon
                 // Collisions
                 if (exportationOptions.ExportCollisions)
                 {
-                    babylonScene.gravity = exportationOptions.Gravity.ToFloat();
                     babylonScene.workerCollisions = exportationOptions.WorkerCollisions;
+                    if (SceneController != null) {
+                        babylonScene.gravity = SceneController.sceneOptions.defaultGravity.ToFloat();
+                    }
                 }
 
                 // Babylon Physics
                 if (exportationOptions.ExportPhysics)
                 {
                     babylonScene.physicsEnabled = true;
-                    babylonScene.physicsGravity = exportationOptions.Gravity.ToFloat();
+                    if (SceneController != null) {
+                        babylonScene.physicsGravity = SceneController.sceneOptions.defaultGravity.ToFloat();
+                    }
                 }
 
                 // Scene Controller
@@ -1332,7 +1333,7 @@ namespace Unity3D2Babylon
                     string[] attributes = babylonLine.Split(':');
                     if (attributes != null && attributes.Length > 1)
                     {
-                        string abuffer = attributes[1].Replace("[", "").Replace("]", "");
+                        string abuffer = attributes[1].Replace("[", "").Replace("]", "").Replace("\"", "");
                         if (!String.IsNullOrEmpty(abuffer))
                         {
                             abuffer = abuffer.Trim();
@@ -1341,7 +1342,7 @@ namespace Unity3D2Babylon
                             {
                                 foreach (string aoption in adata)
                                 {
-                                    string aoption_buffer = aoption.Trim().Replace("\"", "").Trim();
+                                    string aoption_buffer = aoption.Trim();
                                     if (!String.IsNullOrEmpty(aoption_buffer))
                                     {
                                         attributeList.Add(aoption_buffer);
@@ -1356,7 +1357,7 @@ namespace Unity3D2Babylon
                     string[] uniforms = babylonLine.Split(':');
                     if (uniforms != null && uniforms.Length > 1)
                     {
-                        string ubuffer = uniforms[1].Replace("[", "").Replace("]", "");
+                        string ubuffer = uniforms[1].Replace("[", "").Replace("]", "").Replace("\"", "");
                         if (!String.IsNullOrEmpty(ubuffer))
                         {
                             ubuffer = ubuffer.Trim();
@@ -1365,7 +1366,7 @@ namespace Unity3D2Babylon
                             {
                                 foreach (string uoption in udata)
                                 {
-                                    string uoption_buffer = uoption.Trim().Replace("\"", "").Trim();
+                                    string uoption_buffer = uoption.Trim();
                                     if (!String.IsNullOrEmpty(uoption_buffer))
                                     {
                                         uniformList.Add(uoption_buffer);
@@ -1380,7 +1381,7 @@ namespace Unity3D2Babylon
                     string[] samplers = babylonLine.Split(':');
                     if (samplers != null && samplers.Length > 1)
                     {
-                        string sbuffer = samplers[1].Replace("[", "").Replace("]", "");
+                        string sbuffer = samplers[1].Replace("[", "").Replace("]", "").Replace("\"", "");
                         if (!String.IsNullOrEmpty(sbuffer))
                         {
                             sbuffer = sbuffer.Trim();
@@ -1389,7 +1390,7 @@ namespace Unity3D2Babylon
                             {
                                 foreach (string soption in sdata)
                                 {
-                                    string soption_buffer = soption.Trim().Replace("\"", "").Trim();
+                                    string soption_buffer = soption.Trim();
                                     if (!String.IsNullOrEmpty(soption_buffer))
                                     {
                                         samplerList.Add(soption_buffer);
@@ -1404,7 +1405,7 @@ namespace Unity3D2Babylon
                     string[] defines = babylonLine.Split(':');
                     if (defines != null && defines.Length > 1)
                     {
-                        string dbuffer = defines[1].Replace("[", "").Replace("]", "");
+                        string dbuffer = defines[1].Replace("[", "").Replace("]", "").Replace("\"", "");
                         if (!String.IsNullOrEmpty(dbuffer))
                         {
                             dbuffer = dbuffer.Trim();
@@ -1413,7 +1414,7 @@ namespace Unity3D2Babylon
                             {
                                 foreach (string doption in ddata)
                                 {
-                                    string doption_buffer = doption.Trim().Replace("\"", "").Trim();
+                                    string doption_buffer = doption.Trim();
                                     if (!String.IsNullOrEmpty(doption_buffer))
                                     {
                                         defineList.Add(doption_buffer);

+ 6 - 0
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Source/Tools.cs

@@ -20,6 +20,7 @@ namespace Unity3D2Babylon
     public static class Tools
     {
         public static BindingFlags FullBinding = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty;
+        
         public static float[] ToFloat(this Color color)
         {
             var result = new float[4];
@@ -233,6 +234,11 @@ namespace Unity3D2Babylon
             return field.GetValue(instance);
         }
 
+        public static void EnableRemoteCertificates()
+        {
+            System.Net.ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(delegate { return true; });
+        }
+
         public static bool DownloadFile(string url, string dest)
         {
             bool result = false;

+ 3 - 0
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Templates/Config/index.html

@@ -6,6 +6,7 @@
         html, body {
             width: 100%;
             height: 100%;
+            min-height:100%;            
             padding: 0;
             margin: 0;
             overflow: hidden;
@@ -61,6 +62,7 @@
         #cvs {
             width: 100%;
             height: 100%;
+            padding: 0;
             opacity: 0;
             z-index: 0;
             outline: none;
@@ -72,6 +74,7 @@
         #gui {
             width: 100%;
             height: 100%;
+            min-height:100%;            
             z-index: 1;
             outline: none;
             background-color: transparent;

+ 93 - 79
Exporters/Unity 5/EditorToolkit/Assets/Babylon/Templates/Shaders/amiga.template

@@ -1,92 +1,106 @@
 Shader "BabylonJS/NewShaderProgram" {
 	Properties {
 		_Color ("Color", Color) = (1,1,1,1)
+		_Brightness ("Intensity", Range(1.0, 10.0)) = 1.0
 		[NoScaleOffset] _MainTex ("Albedo (RGB)", 2D) = "white" {}
-		_Glossiness ("Smoothness", Range(0,1)) = 0.5
-		_Metallic ("Metallic", Range(0,1)) = 0.0
-		_ScaleX ("Scale Factor X", Range (0.0, 10.0)) = 1.0
-		_ScaleY ("Scale Factor Y", Range (0.0, 10.0)) = 1.0
+		[ToggleOff] _BackFaceCulling ("Back Face Culling", Int) = 1
+		[ToggleOff] _NeedsAlphaTesting ("Needs Alpha Testing", Int) = 0
+		[ToggleOff] _NeedsAlphaBlending ("Needs Alpha Blending", Int) = 0
+		[Enum(Disable,0,Additive,1,Combine,2,Subtract,3,Multiply,4,Maximized,5,OneOne,6)] _AlphaMode ("Alpha Blending Mode", int) = 2
 	}
 	SubShader {
 		Tags { "RenderType"="Opaque" }
-		LOD 200
-		CGPROGRAM
-
-		//////////////////////////////////////////////////////////
-		// BABYLON WEBGL RUNTIME SHADER PROGRAM SECTIONS (GLSL) //
-		//////////////////////////////////////////////////////////
-
-		#ifdef BABYLON
-		attributes: ["position", "normal", "uv"]
-		uniforms: ["worldViewProjection, _Color, _Glossiness, _Metallic, _ScaleX, _ScaleY"]
-		samplers: []
-		defines: []
-		#endif //BABYLON-END
-
-
-		#ifdef VERTEX
-		attribute vec3 position;
-		attribute vec3 normal;
-		attribute vec2 uv;
-		uniform mat4 worldViewProjection;
-		precision highp float;
-
-		varying vec2 vUV;
-		
-		void main(void)
-		{
-			gl_Position = worldViewProjection * vec4(position, 1.0);
-			vUV = uv;
-		}
-		#endif //VERTEX-END
+		LOD 100
+		Pass {
+			CGPROGRAM
 
+			//////////////////////////////////////////////////////////
+			// BABYLON WEBGL RUNTIME SHADER PROGRAM SECTIONS (GLSL) //
+			//////////////////////////////////////////////////////////
 
-		#ifdef FRAGMENT
-		precision highp float;
+			#ifdef BABYLON
+			attributes: "position, normal, uv"
+			uniforms: "worldViewProjection, _Color, _Brightness"
+			samplers: ""
+			defines: ""
+			#endif //BABYLON-END
 
-		varying vec2 vUV;
-		uniform vec4 _Color;
-		uniform float _Glossiness;
-		uniform float _Metallic;
-		uniform float _ScaleX;
-		uniform float _ScaleY;
-		uniform sampler2D _MainTex;
 
-		void main(void)
-		{
-			gl_FragColor = texture2D(_MainTex, vec2(vUV.x * _ScaleX, vUV.y * _ScaleY)) * _Color;
-		}
-		#endif //FRAGMENT-END 
-
-
-		////////////////////////////////////////////////////////
-		// DEFAULT UNITY EDITOR SHADER PROGRAM SECTION (HLSL) //
-		////////////////////////////////////////////////////////
-
-		#pragma exclude_renderers d3d11 xbox360 gles
-		#pragma surface surf Standard fullforwardshadows
-		#pragma target 3.0
-		sampler2D _MainTex;
-		struct Input {
-			float2 uv_MainTex;
-		};
-		half _Glossiness;
-		half _Metallic;
-		half _ScaleX;
-		half _ScaleY;
-		fixed4 _Color;
-		void surf (Input IN, inout SurfaceOutputStandard o) {
-			// Albedo comes from a texture tinted by color
-			float2 vUV = IN.uv_MainTex;
-			fixed4 c = tex2D (_MainTex, float2(vUV.x * _ScaleX, vUV.y * _ScaleY)) * _Color;
-			o.Albedo = c.rgb;
-			// Metallic and smoothness come from slider variables
-			o.Metallic = _Metallic;
-			o.Smoothness = _Glossiness;
-			o.Alpha = c.a;
-		}
+			#ifdef VERTEX
+			attribute vec3 position;
+			attribute vec3 normal;
+			attribute vec2 uv;
+			uniform mat4 worldViewProjection;
+			precision highp float;
+
+			varying vec2 vUV;
+			
+			void main(void)
+			{
+				gl_Position = worldViewProjection * vec4(position, 1.0);
+				vUV = uv;
+			}
+			#endif //VERTEX-END
+
+
+			#ifdef FRAGMENT
+			precision highp float;
+
+			varying vec2 vUV;
+			uniform vec4 _Color;
+			uniform float _Brightness;
+			uniform sampler2D _MainTex;
+
+			void main(void)
+			{
+				// Texture Sample (Unlit)
+				gl_FragColor = texture2D(_MainTex, vUV) * _Color * _Brightness;
+			}
+			#endif //FRAGMENT-END 
 
-		ENDCG
+
+			////////////////////////////////////////////////////////
+			// DEFAULT UNITY EDITOR SHADER PROGRAM SECTION (HLSL) //
+			////////////////////////////////////////////////////////
+
+			#pragma vertex vert
+			#pragma fragment frag
+			
+			#include "UnityCG.cginc"
+
+			struct appdata
+			{
+				float4 vertex : POSITION;
+				float2 uv : TEXCOORD0;
+			};
+
+			struct v2f
+			{
+				float2 uv : TEXCOORD0;
+				float4 vertex : SV_POSITION;
+			};
+
+			float4 _Color;
+			float _Brightness;
+			sampler2D _MainTex;
+			float4 _MainTex_ST;
+
+			v2f vert (appdata v)
+			{
+				v2f o;
+				o.vertex = UnityObjectToClipPos(v.vertex);
+				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
+				return o;
+			}
+			
+			fixed4 frag (v2f i) : SV_Target
+			{
+				// Texture Sample (Unlit)
+				return tex2D(_MainTex, i.uv) * _Color * _Brightness;
+			}
+
+			ENDCG
+		}
 	}
-	FallBack "Diffuse"
-}
+	FallBack "Unlit/Texture"
+}

BIN
Exporters/Unity 5/EditorToolkit/Redist/Asset Store-5.x/BabylonJS/BabylonJS Editor Toolkit.unitypackage


+ 59 - 0
Playground/scripts/instanced bones.js

@@ -0,0 +1,59 @@
+var createScene = function () {
+    var scene = new BABYLON.Scene(engine);
+    var light = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(0, -0.5, -1.0), scene);
+    var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 10, new BABYLON.Vector3(0, 30, 0), scene);
+    
+    camera.attachControl(canvas, false);
+    camera.setPosition(new BABYLON.Vector3(20, 70, 120));
+    light.position = new BABYLON.Vector3(50, 250, 200);
+	light.shadowOrthoScale = 2.0;
+    camera.minZ = 1.0;
+
+    scene.ambientColor = new BABYLON.Color3(0.3, 0.3, 0.3);
+
+    // Ground
+    var ground = BABYLON.Mesh.CreateGround("ground", 1000, 1000, 1, scene, false);
+    var groundMaterial = new BABYLON.StandardMaterial("ground", scene);
+    groundMaterial.diffuseColor = new BABYLON.Color3(0.2, 0.2, 0.2);
+    groundMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
+    ground.material = groundMaterial;
+    ground.receiveShadows = true;
+
+    // Shadows
+    var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
+    shadowGenerator.useBlurVarianceShadowMap = true;
+
+    // Dude
+    BABYLON.SceneLoader.ImportMesh("him", "scenes/Dude/", "Dude.babylon", scene, function (newMeshes2, particleSystems2, skeletons2) {
+        var dude = newMeshes2[0];
+
+        for (var index = 1; index < newMeshes2.length; index++) {
+            shadowGenerator.getShadowMap().renderList.push(newMeshes2[index]);
+        }
+
+        for (var count = 0; count < 50; count++) {
+            var offsetX = 200 * Math.random() - 100;
+            var offsetZ = 200 * Math.random() - 100;
+            for (index = 1; index < newMeshes2.length; index++) {
+                var instance = newMeshes2[index].createInstance("instance" + count);
+
+                shadowGenerator.getShadowMap().renderList.push(instance);
+
+                instance.parent = newMeshes2[index].parent;
+                instance.position = newMeshes2[index].position.clone();
+
+                if (!instance.parent.subMeshes) {
+                    instance.position.x += offsetX;
+                    instance.position.z -= offsetZ;
+                }
+            }
+        }
+
+        dude.rotation.y = Math.PI;
+        dude.position = new BABYLON.Vector3(0, 0, -80);
+
+        scene.beginAnimation(skeletons2[0], 0, 100, true, 1.0);
+    });
+
+    return scene;
+};

+ 2 - 1
Playground/scripts/scripts.txt

@@ -25,4 +25,5 @@ SSAO rendering pipeline
 Volumetric Light Scattering
 HDR Rendering Pipeline
 Refraction and Reflection
-PBR
+PBR
+Instanced bones

+ 4 - 2
Tools/Gulp/config.json

@@ -159,10 +159,10 @@
       "../../src/Math/babylon.math.SIMD.js",
       "../../src/Tools/babylon.rectPackingMap.js",
       "../../src/Tools/babylon.dynamicFloatArray.js",
-      "../../src/Materials/Textures/babylon.fontTexture.js",
       "../../src/Materials/Textures/babylon.mapTexture.js",
       "../../src/Materials/babylon.shaderMaterial.js",
       "../../src/Tools/babylon.tools.dds.js",
+      "../../src/Tools/babylon.khronosTextureContainer.js",
       "../../src/Physics/Plugins/babylon.cannonJSPlugin.js",
       "../../src/Physics/Plugins/babylon.oimoJSPlugin.js",
       "../../src/PostProcess/babylon.displayPassPostProcess.js",
@@ -467,6 +467,7 @@
         "../../canvas2D/src/Tools/babylon.IPropertyChanged.ts",
         "../../canvas2D/src/Tools/babylon.observableArray.ts",
         "../../canvas2D/src/Tools/babylon.observableStringDictionary.ts",
+        "../../canvas2D/src/Engine/babylon.fontTexture.ts",
         "../../canvas2D/src/Engine/babylon.bounding2d.ts",
         "../../canvas2D/src/Engine/babylon.canvas2dLayoutEngine.ts",
         "../../canvas2D/src/Engine/babylon.brushes2d.ts",
@@ -479,6 +480,7 @@
         "../../canvas2D/src/Engine/babylon.rectangle2d.ts",
         "../../canvas2D/src/Engine/babylon.ellipse2d.ts",
         "../../canvas2D/src/Engine/babylon.sprite2d.ts",
+        "../../canvas2D/src/Engine/babylon.atlasPicture.ts",
         "../../canvas2D/src/Engine/babylon.text2d.ts",
         "../../canvas2D/src/Engine/babylon.lines2d.ts",
         "../../canvas2D/src/Engine/babylon.canvas2d.ts",
@@ -491,7 +493,7 @@
         "../../canvas2D/src/GUI/babylon.gui.label.ts",
         "../../canvas2D/src/GUI/babylon.gui.button.ts",
         "../../canvas2D/src/lib.d.ts"
-        ],
+      ],
       "shaderFiles": [
           "../../canvas2D/src/shaders/**.fx", "!../../canvas2D/src/shaders/**.js.fx"
       ],

+ 0 - 1
Tools/Gulp/custom.config.json

@@ -129,7 +129,6 @@
       "../../src/Math/babylon.math.SIMD.js",
       "../../src/Tools/babylon.rectPackingMap.js",
       "../../src/Tools/babylon.dynamicFloatArray.js",
-      "../../src/Materials/Textures/babylon.fontTexture.js",
       "../../src/Materials/Textures/babylon.mapTexture.js",
       "../../src/Materials/babylon.shaderMaterial.js",
       "../../src/Tools/babylon.tools.dds.js",

+ 2 - 1
Tools/Npm/getfiles.bat

@@ -3,5 +3,6 @@ xcopy /Y /F "../../dist/preview release/babylon.js" .
 xcopy /Y /F "../../dist/preview release/babylon.max.js"  .
 xcopy /Y /F "../../dist/preview release/babylon.noworker.js" . 
 xcopy /Y /F "../../dist/preview release/babylon.core.js" . 
+xcopy /Y /F "../../dist/preview release/canvas2D/babylon.canvas2d.js" . 
 xcopy /Y /F "../../dist/preview release/oimo.js" . 
-pause
+pause

+ 3 - 2
Web.config

@@ -1,4 +1,4 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="utf-8"?>
 
 <!--
   For more information on how to configure your ASP.NET application, please visit
@@ -18,6 +18,7 @@
       <mimeMap fileExtension=".dds" mimeType="application/dds" />
       <mimeMap fileExtension=".tga" mimeType="application/tga" />
       <mimeMap fileExtension=".fx" mimeType="application/fx" />
+      <mimeMap fileExtension=".fnt" mimeType="application/bmFont" />
       <mimeMap fileExtension=".babylon" mimeType="application/babylon" />
       <mimeMap fileExtension=".babylonmeshdata" mimeType="application/babylonmeshdata" />
       <mimeMap fileExtension=".babylonbinarymeshdata" mimeType="application/babylonbinarymeshdata" />
@@ -29,4 +30,4 @@
       <!--<mimeMap fileExtension=".mp4" mimeType="video/mp4" />-->
     </staticContent>
   </system.webServer>
-</configuration>
+</configuration>

BIN
assets/meshes/Dude/0.jpg


BIN
assets/meshes/Dude/1.jpg


BIN
assets/meshes/Dude/2.jpg


BIN
assets/meshes/Dude/3.jpg


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
assets/meshes/Dude/dude.babylon


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 5 - 0
assets/meshes/skull.babylon


BIN
assets/textures/sun.png


+ 1 - 1
bower.json

@@ -1,7 +1,7 @@
 {
   "name": "babylonjs",
   "description": "Babylon.js is a complete JavaScript framework for building 3D games with HTML 5 and WebGL",
-  "main": "./dist/babylon.2.4.js",
+  "main": "./dist/babylon.2.5.js",
   "homepage": "https://www.babylonjs.com",
   "repository": {
     "type": "git",

+ 311 - 0
canvas2D/src/Engine/babylon.atlasPicture.ts

@@ -0,0 +1,311 @@
+module BABYLON {
+    /**
+     * Interface to create your own Loader of Atlas Data file.
+     * Call the AtlasPictureInfoFactory.addLoader to addd your loader instance
+     */
+    export interface IAtlasLoader {
+        loadFile(content: any): { api: AtlasPictureInfo, errorMsg: string, errorCode: number };
+    }
+
+    // Proxy Class for the TexturePacker's JSON Array data format
+    interface IFrame {
+        filename: string;
+        frame: { x: number, y: number, w: number, h: number };
+        rotated: boolean;
+        trimmed: boolean;
+        srpiteSourceSize: { x: number, y: number, w: number, h: number };
+        sourceSize: { x: number, y: number, w: number, h: number };
+    }
+
+    // Proxy Class for the TexturePacker's JSON Array data format
+    interface IMeta {
+        app: string;
+        version: string;
+        image: string;
+        format: string;
+        size: { w: number, h: number }
+        scale: string;
+        smartupdate: string;
+    }
+
+    /**
+     * This class will contains information about a sub picture present in an Atlas Picture.
+     */
+    export class AtlasSubPictureInfo {
+        /**
+         * Name of the SubPicture, generally the filename of the initial picture file.
+         */
+        name: string;
+
+        /**
+         * Location of the bottom/left corner of the sub picture from the bottom/left corner the Atlas Picture
+         */
+        location: Vector2;
+
+        /**
+         * Size in pixel of the sub picture
+         */
+        size: Size;
+    }
+
+    /**
+     * This class represent an Atlas Picture, it contains the information of all the sub pictures and the Texture that stores the bitmap.
+     * You get an instance of this class using methods of the AtlasPictureInfoFactory
+     */
+    export class AtlasPictureInfo {
+        /**
+         * Creates many sprite from the Atlas Picture
+         * @param filterCallback a predicate if true is returned then the corresponding sub picture will be used to create a sprite.
+         * The Predicate has many parameters:
+         *  - index: just an index incremented at each sub picture submitted for Sprite creation
+         *  - name: the sub picture's name
+         *  - aspi: the AtlasSubPictureInfo corresponding to the submitted sub picture
+         *  - settings: the Sprite2D creation settings, you can alter this JSON object but BEWARE, the alterations will be kept for subsequent Sprite2D creations!
+         * @param spriteSettings The Sprite2D settings to use for Sprite creation, this JSON object will be passed to the filterCallback for you to alter it, if needed.
+         */
+        createSprites(filterCallback: (index: number, name: string, aspi: AtlasSubPictureInfo, settings: any) => boolean,
+            spriteSettings: {
+                parent?: Prim2DBase,
+                position?: Vector2,
+                x?: number,
+                y?: number,
+                rotation?: number,
+                size?: Size,
+                scale?: number,
+                scaleX?: number,
+                scaleY?: number,
+                dontInheritParentScale?: boolean,
+                opacity?: number,
+                zOrder?: number,
+                origin?: Vector2,
+                scale9?: Vector4,
+                invertY?: boolean,
+                alignToPixel?: boolean,
+                isVisible?: boolean,
+                isPickable?: boolean,
+                isContainer?: boolean,
+                childrenFlatZOrder?: boolean,
+                marginTop?: number | string,
+                marginLeft?: number | string,
+                marginRight?: number | string,
+                marginBottom?: number | string,
+                margin?: number | string,
+                marginHAlignment?: number,
+                marginVAlignment?: number,
+                marginAlignment?: string,
+                paddingTop?: number | string,
+                paddingLeft?: number | string,
+                paddingRight?: number | string,
+                paddingBottom?: number | string,
+                padding?: string,
+            }): Array<Sprite2D> {
+
+            let res = new Array<Sprite2D>();
+
+            let index = 0;
+            this.subPictures.forEach((k, v) => {
+                if (!filterCallback || filterCallback(index++, k, v, spriteSettings)) {
+                    let s = this.createSprite(k, spriteSettings);
+                    if (s) {
+                        res.push(s);
+                    }
+                }
+            });
+            return res;
+        }
+
+        /**
+         * Create one Sprite from a sub picture
+         * @param subPictureName the name of the sub picture to use
+         * @param spriteSettings the Sprite2D settings to use for the Sprite instance creation
+         */
+        createSprite(subPictureName: string, spriteSettings: {
+            parent?: Prim2DBase,
+            position?: Vector2,
+            x?: number,
+            y?: number,
+            rotation?: number,
+            size?: Size,
+            scale?: number,
+            scaleX?: number,
+            scaleY?: number,
+            dontInheritParentScale?: boolean,
+            opacity?: number,
+            zOrder?: number,
+            origin?: Vector2,
+            scale9?: Vector4,
+            invertY?: boolean,
+            alignToPixel?: boolean,
+            isVisible?: boolean,
+            isPickable?: boolean,
+            isContainer?: boolean,
+            childrenFlatZOrder?: boolean,
+            marginTop?: number | string,
+            marginLeft?: number | string,
+            marginRight?: number | string,
+            marginBottom?: number | string,
+            margin?: number | string,
+            marginHAlignment?: number,
+            marginVAlignment?: number,
+            marginAlignment?: string,
+            paddingTop?: number | string,
+            paddingLeft?: number | string,
+            paddingRight?: number | string,
+            paddingBottom?: number | string,
+            padding?: string,
+        }): Sprite2D {
+            let spi = this.subPictures.get(subPictureName);
+            if (!spi) {
+                return null;
+            }
+            if (!spriteSettings) {
+                spriteSettings = {};
+            }
+            let s = <any>spriteSettings;
+            s.id = subPictureName;
+            s.spriteLocation = spi.location;
+            s.spriteSize = spi.size;
+
+            let sprite = new Sprite2D(this.texture, spriteSettings);
+            return sprite;
+        }
+
+        /**
+         * Size of the Atlas Picture
+         */
+        atlasSize: Size;
+
+        /**
+         * String Dictionary of all the sub pictures, the key is the sub picture's name, the value is the info object
+         */
+        subPictures: StringDictionary<AtlasSubPictureInfo>;
+
+        /**
+         * The Texture associated to the Atlas Picture info
+         */
+        texture: Texture;
+    }
+
+    /**
+     * This if the Factory class containing static method to create Atlas Pictures Info objects or add new loaders
+     */
+    export class AtlasPictureInfoFactory {
+        /**
+         * Add a custom loader
+         * @param fileExtension must be the file extension (without the dot) of the file that is loaded by this loader (e.g.: json)
+         * @param plugin the instance of the loader
+         */
+        public static addLoader(fileExtension: string, plugin: IAtlasLoader) {
+            let a = AtlasPictureInfoFactory.plugins.getOrAddWithFactory(fileExtension.toLocaleLowerCase(), () => new Array<IAtlasLoader>());
+            a.push(plugin);
+        }
+
+        /**
+         * Load an Atlas Picture Info object from a data file at a given url and with a given texture
+         * @param texture the texture containing the atlas bitmap
+         * @param url the URL of the Atlas Info data file
+         * @param onLoad a callback that will be called when the AtlasPictureInfo object will be loaded and ready
+         * @param onError a callback that will be called in case of error
+         */
+        public static loadFromUrl(texture: Texture, url: string, onLoad: (api: AtlasPictureInfo) => void, onError: (msg: string, code: number) => void = null) {
+            var xhr = new XMLHttpRequest();
+            xhr.onreadystatechange = () => {
+                if (xhr.readyState === XMLHttpRequest.DONE) {
+                    if (xhr.status === 200) {
+                        let ext = url.split('.').pop().split(/\#|\?/)[0];
+                        let plugins = AtlasPictureInfoFactory.plugins.get(ext.toLocaleLowerCase());
+                        if (!plugins) {
+                            if (onError) {
+                                onError("couldn't find a plugin for this file extension", -1);
+                            }
+                            return;
+                        }
+                        for (let p of plugins) {
+                            let ret = p.loadFile(xhr.response);
+                            if (ret) {
+                                if (ret.api) {
+                                    ret.api.texture = texture;
+                                    if (onLoad) {
+                                        onLoad(ret.api);
+                                    }
+                                } else if (onError) {
+                                    onError(ret.errorMsg, ret.errorCode);
+                                }
+                                return;
+                            }
+                        }
+
+                        if (onError) {
+                            onError("No plugin to load this Atlas Data file format", -1);
+                        }
+
+                    } else {
+                        if (onError) {
+                            onError("Couldn't load file through HTTP Request, HTTP Status " + xhr.status, xhr.status);
+                        }
+                    }
+                }
+            }
+            xhr.open("GET", url, true);
+            xhr.send();
+            return null;
+        }
+
+        private static plugins: StringDictionary<Array<IAtlasLoader>> = new StringDictionary<Array<IAtlasLoader>>();
+    }
+
+     // Loader class for the TexturePacker's JSON Array data format
+    @AtlasLoaderPlugin("json", new JSONArrayLoader())
+    class JSONArrayLoader implements IAtlasLoader {
+
+        loadFile(content): { api: AtlasPictureInfo, errorMsg: string, errorCode: number } {
+            let errorMsg: string = null;
+            let errorCode: number = 0;
+            let root = null;
+            let api: AtlasPictureInfo = null;
+            try {
+                let frames: Array<IFrame>;
+                let meta: IMeta;
+                try {
+                    root = JSON.parse(content);
+                    frames = <Array<IFrame>>root.frames;
+                    meta = <IMeta>root.meta;
+                    if (!frames || !meta) {
+                        throw Error("Not a JSON Array file format");
+                    }
+                } catch (ex1) {
+                    return null;
+                }                 
+
+                api = new AtlasPictureInfo();
+                api.atlasSize = new Size(meta.size.w, meta.size.h);
+                api.subPictures = new StringDictionary<AtlasSubPictureInfo>();
+
+                for (let f of frames) {
+                    let aspi = new AtlasSubPictureInfo();
+                    aspi.name = f.filename;
+                    aspi.location = new Vector2(f.frame.x, api.atlasSize.height - (f.frame.y + f.frame.h));
+                    aspi.size = new Size(f.frame.w, f.frame.h);
+
+                    api.subPictures.add(aspi.name, aspi);
+                }
+            } catch (ex2) {
+                errorMsg = "Unknown Exception: " + ex2;
+                errorCode = -2;
+            } 
+
+            return { api: api, errorMsg: errorMsg, errorCode: errorCode };
+        }
+    }
+
+    /**
+     * Use this decorator when you declare an Atlas Loader Class for the loader to register itself automatically.
+     * @param fileExtension the extension of the file that the plugin is loading (there can be many plugin for the same extension)
+     * @param plugin an instance of the plugin class to add to the AtlasPictureInfoFactory
+     */
+    export function AtlasLoaderPlugin(fileExtension: string, plugin: IAtlasLoader): (target: Object) => void {
+        return () => {
+            AtlasPictureInfoFactory.addLoader(fileExtension, plugin);
+        }
+    }
+}

+ 11 - 2
canvas2D/src/Engine/babylon.canvas2d.ts

@@ -168,7 +168,9 @@
             this._renderingSize = new Size(0, 0);
             this._designSize = settings.designSize || null;
             this._designUseHorizAxis = settings.designUseHorizAxis === true;
-            this._trackedGroups = new Array<Group2D>();
+            if (!this._trackedGroups) {
+                this._trackedGroups = new Array<Group2D>();
+            }
             this._maxAdaptiveWorldSpaceCanvasSize = null;
             this._groupCacheMaps = new StringDictionary<MapTexture[]>();
 
@@ -1278,7 +1280,7 @@
             let v = cam.viewport.toGlobal(this.engine.getRenderWidth(), rh);
 
             for (let group of this._trackedGroups) {
-                if (group.isDisposed || !group.isVisible) {
+                if (group.isDisposed) {
                     continue;
                 }
 
@@ -1286,6 +1288,10 @@
                 let worldMtx = node.getWorldMatrix();
 
                 let proj = Vector3.Project(Canvas2D._v, worldMtx, Canvas2D._m, v);
+
+                // Set the visibility state accordingly, if the position is outside the frustum (well on the Z planes only...) set the group to hidden
+                group.levelVisible = proj.z >= 0 && proj.z < 1.0;
+
                 let s = this.scale;
                 group.x = Math.round(proj.x/s);
                 group.y = Math.round((rh - proj.y)/s);
@@ -1573,6 +1579,9 @@
             if (group._isFlagSet(SmartPropertyPrim.flagTrackedGroup)) {
                 return;
             }
+            if (!this._trackedGroups) {
+                this._trackedGroups = new Array<Group2D>();
+            }
             this._trackedGroups.push(group);
 
             group._setFlags(SmartPropertyPrim.flagTrackedGroup);

+ 467 - 78
src/Materials/Textures/babylon.fontTexture.ts

@@ -17,55 +17,335 @@
         charWidth: number;
     }
 
-    interface ICharInfoMap {
-        [char: string]: CharInfo;
-    }
+    /**
+     * This is an abstract base class to hold a Texture that will contain a FontMap
+     */
+    export abstract class BaseFontTexture extends Texture {
 
-    export class FontTexture extends Texture {
-        private _canvas: HTMLCanvasElement;
-        private _context: CanvasRenderingContext2D;
-        private _lineHeight: number;
-        private _lineHeightSuper: number;
-        private _xMargin: number;
-        private _yMargin: number;
-        private _offset: number;
-        private _currentFreePosition: Vector2;
-        private _charInfos: ICharInfoMap = {};
-        private _curCharCount = 0;
-        private _lastUpdateCharCount = -1;
-        private _spaceWidth;
-        private _spaceWidthSuper;
-        private _usedCounter = 1;
-        private _superSample: boolean;
-        private _sdfCanvas: HTMLCanvasElement;
-        private _sdfContext: CanvasRenderingContext2D;
-        private _signedDistanceField: boolean;
-        private _cachedFontId: string;
-        private _sdfScale: number;
+        constructor(url: string, scene: Scene, noMipmap: boolean = false, invertY: boolean = true, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) {
 
+            super(url, scene, noMipmap, invertY, samplingMode);
+
+            this._cachedFontId = null;
+            this._charInfos = new StringDictionary<CharInfo>();
+        }
+
+        /**
+         * Is the Font is using Super Sampling (each font texel is doubled).
+         */
         public get isSuperSampled(): boolean {
             return this._superSample;
         }
 
+        /**
+         * Is the Font was rendered using the Signed Distance Field algorithm
+         * @returns {} 
+         */
         public get isSignedDistanceField(): boolean {
             return this._signedDistanceField;
         }
 
+        /**
+         * Get the Width (in pixel) of the Space character
+         */
         public get spaceWidth(): number {
             return this._spaceWidth;
         }
 
+        /**
+         * Get the Line height (in pixel)
+         */
         public get lineHeight(): number {
             return this._lineHeight;
         }
 
-        public static GetCachedFontTexture(scene: Scene, fontName: string, supersample: boolean = false, signedDistanceField: boolean = false) {
-            let s = <any>scene;
-            if (!s.__fontTextureCache__) {
-                s.__fontTextureCache__ = new StringDictionary<FontTexture>();
+        /**
+         * When the FontTexture is retrieved through the FontCache, there's a reference counter that is incremented for each use.
+         * You also have the possibility to extend the lifetime of the FontTexture when passing it to another object by calling this method
+         * Don't forget to call the corresponding decCachedFontTextureCounter method when you no longer have use of the FontTexture.
+         * Each call to incCachedFontTextureCounter must have a corresponding call to decCachedFontTextureCounter.
+         */
+        abstract incCachedFontTextureCounter();
+
+        /**
+         * Decrement the reference counter, if it reaches 0 the FontTexture is disposed
+         */
+        abstract decCachedFontTextureCounter();
+
+        /**
+         * Is the font dynamically updated, if true is returned then you have to call the update() before using the font in rendering if new character were adding using getChar()
+         */
+        abstract get isDynamicFontTexture(): boolean;
+
+        /**
+         * Will fetch the new characters retrieved with getChar() to the texture.
+         * If there were no new char, this call is harmless and quit in no time.
+         * If there were new chars a texture lock/update is made, which is a costy operation.
+         */
+        abstract update(): void;
+
+        /**
+         * Measure the width/height that will take a given text
+         * @param text the text to measure
+         * @param tabulationSize the size (in space character) of the tabulation character, default value must be 4
+         */
+        measureText(text: string, tabulationSize?: number): Size {
+            let maxWidth: number = 0;
+            let curWidth: number = 0;
+            let lineCount = 1;
+            let charxpos: number = 0;
+
+            // Parse each char of the string
+            for (var char of text) {
+
+                // Next line feed?
+                if (char === "\n") {
+                    maxWidth = Math.max(maxWidth, curWidth);
+                    charxpos = 0;
+                    curWidth = 0;
+                    ++lineCount;
+                    continue;
+                }
+
+                // Tabulation ?
+                if (char === "\t") {
+                    let nextPos = charxpos + tabulationSize;
+                    nextPos = nextPos - (nextPos % tabulationSize);
+
+                    curWidth += (nextPos - charxpos) * this.spaceWidth;
+                    charxpos = nextPos;
+                    continue;
+                }
+
+                if (char < " ") {
+                    continue;
+                }
+
+                let ci = this.getChar(char);
+                if (!ci) {
+                    throw new Error(`Character ${char} is not supported by FontTexture ${this.name}`);
+                }
+                curWidth += ci.charWidth;
+                ++charxpos;
+            }
+            maxWidth = Math.max(maxWidth, curWidth);
+
+            return new Size(maxWidth, lineCount * this.lineHeight);
+        }
+
+        /**
+         * Retrieve the CharInfo object for a given character
+         * @param char the character to retrieve the CharInfo object from (e.g.: "A", "a", etc.)
+         */
+        abstract getChar(char: string): CharInfo;
+
+        protected _charInfos: StringDictionary<CharInfo>;
+        protected _lineHeight: number;
+        protected _spaceWidth;
+        protected _superSample: boolean;
+        protected _signedDistanceField: boolean;
+        protected _cachedFontId: string;
+    }
+
+    export class BitmapFontInfo {
+        kerningDic = new StringDictionary<number>();
+        charDic = new StringDictionary<CharInfo>();
+
+        textureSize : Size;
+        atlasName   : string;
+        padding     : Vector4;       // Left, Top, Right, Bottom
+        lineHeight: number;
+        textureUrl  : string;
+        textureFile : string;
+    }
+
+    export interface IBitmapFontLoader {
+        loadFont(fontDataContent: any, scene: Scene, invertY: boolean): { bfi: BitmapFontInfo, errorMsg: string, errorCode: number };
+    }
+
+    export class BitmapFontTexture extends BaseFontTexture {
+        public constructor( scene: Scene,
+                            bmFontUrl: string,
+                            textureUrl: string = null,
+                            noMipmap: boolean = false,
+                            invertY: boolean = true,
+                            samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, 
+                            onLoad: () => void = null,
+                            onError: (msg: string, code: number) => void = null)
+        {
+            super(null, scene, noMipmap, invertY, samplingMode);
+
+            var xhr = new XMLHttpRequest();
+            xhr.onreadystatechange = () => {
+                if (xhr.readyState === XMLHttpRequest.DONE) {
+                    if (xhr.status === 200) {
+                        let ext = bmFontUrl.split('.').pop().split(/\#|\?/)[0];
+                        let plugins = BitmapFontTexture.plugins.get(ext.toLocaleLowerCase());
+                        if (!plugins) {
+                            if (onError) {
+                                onError("couldn't find a plugin for this file extension", -1);
+                            }
+                            return;
+                        }
+
+                        for (let p of plugins) {
+                            let ret = p.loadFont(xhr.response, scene, invertY);
+                            if (ret) {
+                                let bfi = ret.bfi;
+
+                                if (textureUrl != null) {
+                                    bfi.textureUrl = textureUrl;
+                                } else {
+                                    let baseUrl = bmFontUrl.substr(0, bmFontUrl.lastIndexOf("/") + 1);
+                                    bfi.textureUrl = baseUrl + bfi.textureFile;
+                                }
+
+                                this._texture = scene.getEngine().createTexture(bfi.textureUrl, noMipmap, invertY, scene, samplingMode, () => {
+                                    if (ret.bfi && onLoad) {
+                                        onLoad();
+                                    }
+                                });
+
+                                this._lineHeight = bfi.lineHeight;
+                                this._charInfos.copyFrom(bfi.charDic);
+                                let ci = this.getChar(" ");
+                                if (ci) {
+                                    this._spaceWidth = ci.charWidth;
+                                } else {
+                                    this._charInfos.first((k, v) => this._spaceWidth = v.charWidth);
+                                }
+
+                                if (!ret.bfi && onError) {
+                                    onError(ret.errorMsg, ret.errorCode);
+                                }
+                                return;
+                            }
+                        }
+
+                        if (onError) {
+                            onError("No plugin to load this BMFont file format", -1);
+                        }
+                    } else {
+                        if (onError) {
+                            onError("Couldn't load file through HTTP Request, HTTP Status " + xhr.status, xhr.status);
+                        }
+                    }
+                }
+            }
+            xhr.open("GET", bmFontUrl, true);
+            xhr.send();
+        }
+
+        public static GetCachedFontTexture(scene: Scene, fontTexture: BitmapFontTexture): BitmapFontTexture {
+            let dic = scene.getOrAddExternalDataWithFactory("BitmapFontTextureCache", () => new StringDictionary<BitmapFontTexture>());
+
+            let ft = dic.get(fontTexture.uid);
+            if (ft) {
+                ++ft._usedCounter;
+                return ft;
+            }
+
+            dic.add(fontTexture.uid, fontTexture);
+
+            return ft;
+        }
+
+        public static ReleaseCachedFontTexture(scene: Scene, fontTexture: BitmapFontTexture) {
+            let dic = scene.getExternalData<StringDictionary<BitmapFontTexture>>("BitmapFontTextureCache");
+            if (!dic) {
+                return;
+            }
+
+            var font = dic.get(fontTexture.uid);
+            if (--font._usedCounter === 0) {
+                dic.remove(fontTexture.uid);
+                font.dispose();
+            }
+        }
+
+        /**
+         * Is the font dynamically updated, if true is returned then you have to call the update() before using the font in rendering if new character were adding using getChar()
+         */
+        get isDynamicFontTexture(): boolean {
+            return false;
+        }
+
+        /**
+         * This method does nothing for a BitmapFontTexture object as it's a static texture
+         */
+        update(): void {
+        }
+
+        /**
+         * Retrieve the CharInfo object for a given character
+         * @param char the character to retrieve the CharInfo object from (e.g.: "A", "a", etc.)
+         */
+        getChar(char: string): CharInfo {
+            return this._charInfos.get(char);
+        }
+
+        /**
+         * For FontTexture retrieved using GetCachedFontTexture, use this method when you transfer this object's lifetime to another party in order to share this resource.
+         * When the other party is done with this object, decCachedFontTextureCounter must be called.
+         */
+        public incCachedFontTextureCounter() {
+            ++this._usedCounter;
+        }
+
+        /**
+         * Use this method only in conjunction with incCachedFontTextureCounter, call it when you no longer need to use this shared resource.
+         */
+        public decCachedFontTextureCounter() {
+            let dic = this.getScene().getExternalData<StringDictionary<BitmapFontTexture>>("BitmapFontTextureCache");
+            if (!dic) {
+                return;
+            }
+            if (--this._usedCounter === 0) {
+                dic.remove(this._cachedFontId);
+                this.dispose();
             }
+        }
+        private _usedCounter = 1;
+
+        static addLoader(fileExtension: string, plugin: IBitmapFontLoader) {
+            let a = BitmapFontTexture.plugins.getOrAddWithFactory(fileExtension.toLocaleLowerCase(), () => new Array<IBitmapFontLoader>());
+            a.push(plugin);
+        }
+
+        static plugins: StringDictionary<IBitmapFontLoader[]> = new StringDictionary<Array<IBitmapFontLoader>>();
+    }
+
+    /**
+     * This class is a special kind of texture which generates on the fly characters of a given css style "fontName".
+     * The generated texture will be updated when new characters will be retrieved using the getChar() method, but you have
+     *  to call the update() method for the texture to fetch these changes, you can harmlessly call update any time you want, if no
+     *  change were made, nothing will happen.
+     * The Font Texture can be rendered in three modes: normal size, super sampled size (x2) or using Signed Distance Field rendering.
+     * Signed Distance Field should be prefered because the texture can be rendered using AlphaTest instead of Transparency, which is way more faster. More about SDF here (http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf).
+     * The only flaw of SDF is that the rendering quality may not be the best or the edges too sharp is the font thickness is too thin.
+     */
+    export class FontTexture extends BaseFontTexture {
+        private _canvas: HTMLCanvasElement;
+        private _context: CanvasRenderingContext2D;
+        private _lineHeightSuper: number;
+        private _xMargin: number;
+        private _yMargin: number;
+        private _offset: number;
+        private _currentFreePosition: Vector2;
+        private _curCharCount = 0;
+        private _lastUpdateCharCount = -1;
+        private _spaceWidthSuper;
+        private _sdfCanvas: HTMLCanvasElement;
+        private _sdfContext: CanvasRenderingContext2D;
+        private _sdfScale: number;
+        private _usedCounter = 1;
 
-            let dic = <StringDictionary<FontTexture>>s.__fontTextureCache__;
+        get isDynamicFontTexture(): boolean {
+            return true;
+        }
+
+        public static GetCachedFontTexture(scene: Scene, fontName: string, supersample: boolean = false, signedDistanceField: boolean = false): FontTexture {
+            let dic = scene.getOrAddExternalDataWithFactory("FontTextureCache", () => new StringDictionary<FontTexture>());
 
             let lfn = fontName.toLocaleLowerCase() + (supersample ? "_+SS" : "_-SS") + (signedDistanceField ? "_+SDF" : "_-SDF");
             let ft = dic.get(lfn);
@@ -82,8 +362,7 @@
         }
 
         public static ReleaseCachedFontTexture(scene: Scene, fontName: string, supersample: boolean = false, signedDistanceField: boolean = false) {
-            let s = <any>scene;
-            let dic = <StringDictionary<FontTexture>>s.__fontTextureCache__;
+            let dic = scene.getExternalData<StringDictionary<FontTexture>>("FontTextureCache");
             if (!dic) {
                 return;
             }
@@ -105,7 +384,8 @@
          * @param samplingMode the texture sampling mode
          * @param superSample if true the FontTexture will be created with a font of a size twice bigger than the given one but all properties (lineHeight, charWidth, etc.) will be according to the original size. This is made to improve the text quality.
          */
-        constructor(name: string, font: string, scene: Scene, maxCharCount=200, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, superSample: boolean = false, signedDistanceField: boolean = false) {
+        constructor(name: string, font: string, scene: Scene, maxCharCount = 200, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, superSample: boolean = false, signedDistanceField: boolean = false) {
+
             super(null, scene, true, false, samplingMode);
 
             this.name = name;
@@ -132,7 +412,6 @@
             this._context.font = font;
             this._context.fillStyle = "white";
             this._context.textBaseline = "top";
-            this._cachedFontId = null;
 
             var res = this.getFontHeight(font);
             this._lineHeightSuper = res.height+4;
@@ -207,7 +486,7 @@
                 return null;
             }
 
-            var info = this._charInfos[char];
+            var info = this._charInfos.get(char);
             if (info) {
                 return info;
             }
@@ -255,7 +534,7 @@
             info.charWidth = this._superSample ? (width/2) : width;
 
             // Add the info structure
-            this._charInfos[char] = info;
+            this._charInfos.add(char, info);
             this._curCharCount++;
 
             // Set the next position
@@ -411,46 +690,6 @@
             return res;
         }
 
-        public measureText(text: string, tabulationSize: number = 4): Size {
-            let maxWidth: number = 0;
-            let curWidth: number = 0;
-            let lineCount = 1;
-            let charxpos: number = 0;
-
-            // Parse each char of the string
-            for (var char of text) {
-
-                // Next line feed?
-                if (char === "\n") {
-                    maxWidth = Math.max(maxWidth, curWidth);
-                    charxpos = 0;
-                    curWidth = 0;
-                    ++lineCount;
-                    continue;
-                }
-
-                // Tabulation ?
-                if (char === "\t") {
-                    let nextPos = charxpos + tabulationSize;
-                    nextPos = nextPos - (nextPos % tabulationSize);
-
-                    curWidth += (nextPos - charxpos) * this.spaceWidth;
-                    charxpos = nextPos;
-                    continue;
-                }
-
-                if (char < " ") {
-                    continue;
-                }
-
-                curWidth += this.getChar(char).charWidth;
-                ++charxpos;
-            }
-            maxWidth = Math.max(maxWidth, curWidth);
-
-            return new Size(maxWidth, lineCount * this.lineHeight);
-        }
-
         private getSuperSampleFont(font: string): string {
             // Eternal thank to http://stackoverflow.com/a/10136041/802124
             let regex = /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\"\sa-z]+?)\s*$/;
@@ -541,15 +780,165 @@
          * Use this method only in conjunction with incCachedFontTextureCounter, call it when you no longer need to use this shared resource.
          */
         public decCachedFontTextureCounter() {
-            let s = <any>this.getScene();
-            let dic = <StringDictionary<FontTexture>>s.__fontTextureCache__;
+            let dic = this.getScene().getExternalData<StringDictionary<FontTexture>>("FontTextureCache");
             if (!dic) {
                 return;
             }
             if (--this._usedCounter === 0) {
                 dic.remove(this._cachedFontId);
                 this.dispose();
-            }         
+            }
         }
+
     }
+
+    /**
+     * Orginial code from cocos2d-js, converted to TypeScript by Nockawa
+     * Load the Text version of the BMFont format, no XML or binary supported, just plain old text
+     */
+    @BitmapFontLoaderPlugin("fnt", new BMFontLoaderTxt())
+    class BMFontLoaderTxt implements IBitmapFontLoader {
+        private static INFO_EXP    = /info [^\r\n]*(\r\n|$)/gi;
+        private static COMMON_EXP  = /common [^\n]*(\n|$)/gi;
+        private static PAGE_EXP    = /page [^\n]*(\n|$)/gi;
+        private static CHAR_EXP    = /char [^\n]*(\n|$)/gi;
+        private static KERNING_EXP = /kerning [^\n]*(\n|$)/gi;
+        private static ITEM_EXP    = /\w+=[^ \r\n]+/gi;
+        private static INT_EXP     = /^[\-]?\d+$/;
+
+        private _parseStrToObj(str) {
+            var arr = str.match(BMFontLoaderTxt.ITEM_EXP);
+            if (!arr) {
+                return null;
+            }
+
+            var obj = {};
+            for (var i = 0, li = arr.length; i < li; i++) {
+                var tempStr = arr[i];
+                var index = tempStr.indexOf("=");
+                var key = tempStr.substring(0, index);
+                var value = tempStr.substring(index + 1);
+                if (value.match(BMFontLoaderTxt.INT_EXP)) value = parseInt(value);
+                else if (value[0] === '"') value = value.substring(1, value.length - 1);
+                obj[key] = value;
+            }
+            return obj;
+        }
+
+        private _buildCharInfo(initialLine: string, obj: any, textureSize: Size, invertY: boolean, chars: StringDictionary<CharInfo>) {
+            let char: string = null;
+            let x: number = null;
+            let y: number = null;
+            let xadv: number = null;
+            let width: number = null;
+            let height: number = null;
+            let ci = new CharInfo();
+            for (let key in obj) {
+                let value = obj[key];
+                switch (key) {
+                    case "id":
+                        char = String.fromCharCode(value);
+                        break;
+                    case "x":
+                        x = value;
+                        break;
+                    case "y":
+                        y = value;
+                        break;
+                    case "width":
+                        width = value;
+                        break;
+                    case "height":
+                        height = value;
+                        break;
+                    case "xadvance":
+                        xadv = value;
+                        break;
+                }
+            }
+
+            if (x != null && y != null && width != null && height != null && char != null) {
+                if (xadv) {
+                    width = xadv;
+                }
+                if (invertY) {
+                    ci.topLeftUV = new Vector2(1 - (x / textureSize.width), 1 - (y / textureSize.height));
+                    ci.bottomRightUV = new Vector2(1 - ((x + width) / textureSize.width), 1 - ((y + height) / textureSize.height));
+                } else {
+                    ci.topLeftUV = new Vector2(x / textureSize.width, y / textureSize.height);
+                    ci.bottomRightUV = new Vector2((x + width) / textureSize.width, (y + height) / textureSize.height);
+                }
+                ci.charWidth = width;
+                chars.add(char, ci);
+            } else {
+                console.log("Error while parsing line " + initialLine);
+            }
+        }
+
+        public loadFont(fontContent: any, scene: Scene, invertY: boolean): { bfi: BitmapFontInfo, errorMsg: string, errorCode: number } {
+            let fontStr = <string>fontContent;
+            let bfi = new BitmapFontInfo();
+            let errorCode = 0;
+            let errorMsg = "OK";
+
+            //padding
+            let info = fontStr.match(BMFontLoaderTxt.INFO_EXP);
+            let infoObj = this._parseStrToObj(info[0]);
+            if (!infoObj) {
+                return null;
+            }
+            let paddingArr = infoObj["padding"].split(",");
+            bfi.padding = new Vector4(parseInt(paddingArr[0]), parseInt(paddingArr[1]), parseInt(paddingArr[2]), parseInt(paddingArr[3]));
+
+            //common
+            var commonObj = this._parseStrToObj(fontStr.match(BMFontLoaderTxt.COMMON_EXP)[0]);
+            bfi.lineHeight = commonObj["lineHeight"];
+            bfi.textureSize = new Size(commonObj["scaleW"], commonObj["scaleH"]);
+
+            var maxTextureSize = scene.getEngine()._gl.getParameter(0xd33);
+            if (commonObj["scaleW"] > maxTextureSize.width || commonObj["scaleH"] > maxTextureSize.height) {
+                errorMsg = "FontMap texture's size is bigger than what WebGL supports";
+                errorCode = -1;
+            } else {
+                if (commonObj["pages"] !== 1) {
+                    errorMsg = "FontMap must contain one page only.";
+                    errorCode = -1;
+                } else {
+                    //page
+                    let pageObj = this._parseStrToObj(fontStr.match(BMFontLoaderTxt.PAGE_EXP)[0]);
+                    if (pageObj["id"] !== 0) {
+                        errorMsg = "Only one page of ID 0 is supported";
+                        errorCode = -1;
+                    } else {
+                        bfi.textureFile = pageObj["file"];
+
+                        //char
+                        let charLines = fontStr.match(BMFontLoaderTxt.CHAR_EXP);
+                        for (let i = 0, li = charLines.length; i < li; i++) {
+                            let charObj = this._parseStrToObj(charLines[i]);
+                            this._buildCharInfo(charLines[i], charObj, bfi.textureSize, invertY, bfi.charDic);
+                        }
+
+                        //kerning
+                        var kerningLines = fontStr.match(BMFontLoaderTxt.KERNING_EXP);
+                        if (kerningLines) {
+                            for (let i = 0, li = kerningLines.length; i < li; i++) {
+                                let kerningObj = this._parseStrToObj(kerningLines[i]);
+                                bfi.kerningDic.add(((kerningObj["first"] << 16) | (kerningObj["second"] & 0xffff)).toString(), kerningObj["amount"]);
+                            }
+                        }
+                    }
+                }
+
+            }
+            return { bfi: bfi, errorCode: errorCode, errorMsg: errorMsg };
+        }
+    };
+
+    export function BitmapFontLoaderPlugin(fileExtension: string, plugin: IBitmapFontLoader): (target: Object) => void {
+        return () => {
+            BitmapFontTexture.addLoader(fileExtension, plugin);
+        }
+    }
+
 } 

+ 8 - 1
canvas2D/src/Engine/babylon.prim2dBase.ts

@@ -1943,7 +1943,10 @@
          */
         @dynamicLevelProperty(SmartPropertyPrim.SMARTPROPERTYPRIM_PROPCOUNT + 6, pi => Prim2DBase.sizeProperty = pi, false, true)
         public get size(): Size {
+            return this.internalGetSize();
+        }
 
+        protected internalGetSize(): Size {
             if (!this._size || this._size.width == null || this._size.height == null) {
 
                 if (Prim2DBase.boundinbBoxReentrency) {
@@ -1961,11 +1964,14 @@
                 return this._boundingSize;
 
             }
-
             return this._size;
         }
 
         public set size(value: Size) {
+            this.internalSetSize(value);
+        }
+
+        protected internalSetSize(value: Size) {
             this._size = value;
         }
 
@@ -3134,6 +3140,7 @@
                 this._actionManager.dispose();
                 this._actionManager = null;
             }
+            this.owner.scene.stopAnimation(this);
 
             // If there's a parent, remove this object from its parent list
             if (this._parent) {

+ 16 - 9
canvas2D/src/Engine/babylon.renderablePrim2d.ts

@@ -27,6 +27,9 @@
                     // Only map if there's no category assigned to the instance data or if there's a category and it's in the given list
                     if (!attrib.category || categories.indexOf(attrib.category) !== -1) {
                         let index = effect.getAttributeLocationByName(attrib.attributeName);
+                        if (index === - 1) {
+                            throw new Error(`Attribute ${attrib.attributeName} was not found in Effect: ${effect.name}. It's certainly no longer used in the Effect's Shaders`);
+                        }
                         let iai = new InstancingAttributeInfo();
                         iai.index = index;
                         iai.attributeSize = attrib.size / 4; // attrib.size is in byte and we need to store in "component" (i.e float is 1, vec3 is 3)
@@ -932,13 +935,6 @@
         protected updateInstanceDataPart(part: InstanceDataBase, positionOffset: Vector2 = null) {
             let t = this._globalTransform.multiply(this.renderGroup.invGlobalTransform);    // Compute the transformation into the renderGroup's space
             let rgScale = this._areSomeFlagsSet(SmartPropertyPrim.flagDontInheritParentScale) ? RenderablePrim2D._uV : this.renderGroup.actualScale;         // We still need to apply the scale of the renderGroup to our rendering, so get it.
-
-            if (!this.applyActualScaleOnTransform() || rgScale.x!==1 || rgScale.y!==1) {
-                t.decompose(RenderablePrim2D._s, RenderablePrim2D._r, RenderablePrim2D._t);
-                t = Matrix.Compose((!this.applyActualScaleOnTransform() ? RenderablePrim2D._uV3.divide(new Vector3(rgScale.x, rgScale.y, 1)) : RenderablePrim2D._s), RenderablePrim2D._r, RenderablePrim2D._t);
-            }
-
-            //let rgScale = (this._areSomeFlagsSet(SmartPropertyPrim.flagDontInheritParentScale) || !this.applyActualScaleOnTransform()) ? RenderablePrim2D._uV : this.renderGroup.actualScale;         // We still need to apply the scale of the renderGroup to our rendering, so get it.
             let size = (<Size>this.renderGroup.viewportSize);
             let zBias = this.actualZOffset;
 
@@ -959,8 +955,19 @@
             let w = size.width;
             let h = size.height;
             let invZBias = 1 / zBias;
-            let tx = new Vector4(t.m[0] * 2 / w, t.m[4] * 2 / w, 0/*t.m[8]*/, ((t.m[12] + offX) * 2 / w) - 1);
-            let ty = new Vector4(t.m[1] * 2 / h, t.m[5] * 2 / h, 0/*t.m[9]*/, ((t.m[13] + offY) * 2 / h) - 1);
+            let tx = new Vector4(t.m[0] * rgScale.x * 2 / w, t.m[4] * rgScale.x * 2 / w, 0/*t.m[8]*/, ((t.m[12] + offX) * rgScale.x * 2 / w) - 1);
+            let ty = new Vector4(t.m[1] * rgScale.y * 2 / h, t.m[5] * rgScale.y * 2 / h, 0/*t.m[9]*/, ((t.m[13] + offY) * rgScale.y * 2 / h) - 1);
+
+            if (!this.applyActualScaleOnTransform()) {
+                t.m[0] = tx.x, t.m[4] = tx.y, t.m[12] = tx.w;
+                t.m[1] = ty.x, t.m[5] = ty.y, t.m[13] = ty.w;
+                let las = this.actualScale;
+                t.decompose(RenderablePrim2D._s, RenderablePrim2D._r, RenderablePrim2D._t);
+                let scale = new Vector3(RenderablePrim2D._s.x / las.x, RenderablePrim2D._s.y / las.y, 1);
+                t = Matrix.Compose(scale, RenderablePrim2D._r, RenderablePrim2D._t);
+                tx = new Vector4(t.m[0], t.m[4], 0, t.m[12]);
+                ty = new Vector4(t.m[1], t.m[5], 0, t.m[13]);
+            }
 
             part.transformX = tx;
             part.transformY = ty;

+ 163 - 93
canvas2D/src/Engine/babylon.sprite2d.ts

@@ -85,51 +85,6 @@
         }
     }
 
-    export class Sprite2DInstanceData extends InstanceDataBase {
-        constructor(partId: number) {
-            super(partId, 1);
-        }
-
-        @instanceData()
-        get topLeftUV(): Vector2 {
-            return null;
-        }
-        set topLeftUV(value: Vector2) {
-        }
-
-        @instanceData()
-        get sizeUV(): Vector2 {
-            return null;
-        }
-        set sizeUV(value: Vector2) {
-        }
-
-        @instanceData()
-        get scaleFactor(): Vector2 {
-            return null;
-        }
-        set scaleFactor(value: Vector2) {
-        }
-
-        @instanceData()
-        get textureSize(): Vector2 {
-            return null;
-        }
-        set textureSize(value: Vector2) {
-        }
-
-        // 3 floats being:
-        // - x: frame number to display
-        // - y: invertY setting
-        // - z: alignToPixel setting
-        @instanceData()
-        get properties(): Vector3 {
-            return null;
-        }
-        set properties(value: Vector3) {
-        }
-    }
-
     @className("Sprite2D", "BABYLON")
     /**
      * Primitive that displays a Sprite/Picture
@@ -137,13 +92,16 @@
     export class Sprite2D extends RenderablePrim2D {
         static SPRITE2D_MAINPARTID = 1;
 
+        static SHAPE2D_CATEGORY_SCALE9 = "Scale9";
+
         public static textureProperty: Prim2DPropInfo;
         public static useAlphaFromTextureProperty: Prim2DPropInfo;
         public static actualSizeProperty: Prim2DPropInfo;
+        public static spriteSizeProperty: Prim2DPropInfo;
         public static spriteLocationProperty: Prim2DPropInfo;
         public static spriteFrameProperty: Prim2DPropInfo;
         public static invertYProperty: Prim2DPropInfo;
-        public static spriteScaleFactorProperty: Prim2DPropInfo;
+        public static spriteScale9Property: Prim2DPropInfo;
 
         @modelLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 1, pi => Sprite2D.textureProperty = pi)
         /**
@@ -174,6 +132,19 @@
             this._updateRenderMode();
         }
 
+        public get size(): Size {
+            if (this._size == null) {
+                return this.spriteSize;
+            }
+            return this.internalGetSize();
+        }
+
+        public set size(value: Size) {
+            this._useSize = value != null;
+            this.internalSetSize(value);
+            this._updateSpriteScaleFactor();
+        }
+
         @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 3, pi => Sprite2D.actualSizeProperty = pi, false, true)
         /**
          * Get/set the actual size of the sprite to display
@@ -189,19 +160,32 @@
             this._actualSize = value;
         }
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 4, pi => Sprite2D.spriteLocationProperty = pi)
+        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 4, pi => Sprite2D.spriteSizeProperty = pi)
+        /**
+         * Get/set the sprite location (in pixels) in the texture
+         */
+        public get spriteSize(): Size {
+            return this._spriteSize;
+        }
+
+        public set spriteSize(value: Size) {
+            this._spriteSize = value;
+            this._updateSpriteScaleFactor();
+        }
+
+        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 5, pi => Sprite2D.spriteLocationProperty = pi)
         /**
          * Get/set the sprite location (in pixels) in the texture
          */
         public get spriteLocation(): Vector2 {
-            return this._location;
+            return this._spriteLocation;
         }
 
         public set spriteLocation(value: Vector2) {
-            this._location = value;
+            this._spriteLocation = value;
         }
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 5, pi => Sprite2D.spriteFrameProperty = pi)
+        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 6, pi => Sprite2D.spriteFrameProperty = pi)
         /**
          * Get/set the sprite frame to display.
          * The frame number is just an offset applied horizontally, based on the sprite's width. it does not wrap, all the frames must be on the same line.
@@ -214,7 +198,7 @@
             this._spriteFrame = value;
         }
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 6, pi => Sprite2D.invertYProperty = pi)
+        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 7, pi => Sprite2D.invertYProperty = pi)
         /**
          * Get/set if the sprite texture coordinates should be inverted on the Y axis
          */
@@ -226,42 +210,25 @@
             this._invertY = value;
         }
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 7, pi => Sprite2D.spriteScaleFactorProperty = pi)
+        @modelLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 8, pi => Sprite2D.spriteScale9Property = pi)
         /**
-         * Get/set the sprite location (in pixels) in the texture
+         * Get/set the texture that contains the sprite to display
          */
-        public get spriteScaleFactor(): Vector2 {
-            return this._spriteScaleFactor;
+        public get isScale9(): boolean {
+            return this._scale9!==null;
         }
 
-        public set spriteScaleFactor(value: Vector2) {
-            this._spriteScaleFactor = value;
-        }
+        //@instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 7, pi => Sprite2D.spriteScaleFactorProperty = pi)
+        ///**
+        // * Get/set the sprite location (in pixels) in the texture
+        // */
+        //public get spriteScaleFactor(): Vector2 {
+        //    return this._spriteScaleFactor;
+        //}
 
-        /**
-         * Sets the scale of the sprite using a BABYLON.Size(w,h).
-         * Keeps proportion by taking the maximum of the two scale for x and y.
-         * @param {Size} size Size(width,height)
-         */
-        public scaleToSize(size: Size) {
-            var baseSize = this.size;
-            if (baseSize == null || !this.texture.isReady()) {
-                // we're probably at initiation of the scene, size is not set
-                if (this.texture.isReady()) {
-                    baseSize = <Size>this.texture.getBaseSize();
-                }
-                else {
-                    // the texture is not ready, wait for it to load before calling scaleToSize again
-                    var thisObject = <Sprite2D>this;
-                    this.texture.onLoadObservable.add(function () {
-                            thisObject.scaleToSize(size); 
-                        });
-                    return;
-                }
-            }
-            
-            this.scale = Math.max(size.height / baseSize.height, size.width / baseSize.width);
-        }
+        //public set spriteScaleFactor(value: Vector2) {
+        //    this._spriteScaleFactor = value;
+        //}
 
         /**
          * Get/set if the sprite rendering should be aligned to the target rendering device pixel or not
@@ -295,6 +262,10 @@
             return true;
         }
 
+        public get isSizeAuto(): boolean {
+            return this.size == null;
+        }
+
         /**
          * Create an 2D Sprite primitive
          * @param texture the texture that stores the sprite to render
@@ -305,13 +276,15 @@
          * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
          * - rotation: the initial rotation (in radian) of the primitive. default is 0
          * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
+         * - size: the size of the sprite displayed in the canvas, if not specified the spriteSize will be used
          * - dontInheritParentScale: if set the parent's scale won't be taken into consideration to compute the actualScale property
          * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
          * - zOrder: override the zOrder with the specified value
          * - origin: define the normalized origin point location, default [0.5;0.5]
-         * - spriteSize: the size of the sprite (in pixels), if null the size of the given texture will be used, default is null.
+         * - spriteSize: the size of the sprite (in pixels) as it is stored in the texture, if null the size of the given texture will be used, default is null.
          * - spriteLocation: the location (in pixels) in the texture of the top/left corner of the Sprite to display, default is null (0,0)
-         * - spriteScaleFactor: say you want to display a sprite twice as big as its bitmap which is 64,64, you set the spriteSize to 128,128 and have to set the spriteScaleFactory to 0.5,0.5 in order to address only the 64,64 pixels of the bitmaps. Default is 1,1.
+         * - spriteScaleFactor: DEPRECATED. Old behavior: say you want to display a sprite twice as big as its bitmap which is 64,64, you set the spriteSize to 128,128 and have to set the spriteScaleFactory to 0.5,0.5 in order to address only the 64,64 pixels of the bitmaps. Default is 1,1.
+         * - scale9: draw the sprite as a Scale9 sprite, see http://yannickloriot.com/2013/03/9-patch-technique-in-cocos2d/ for more info. x, y, w, z are left, bottom, right, top coordinate of the resizable box
          * - invertY: if true the texture Y will be inverted, default is false.
          * - alignToPixel: if true the sprite's texels will be aligned to the rendering viewport pixels, ensuring the best rendering quality but slow animations won't be done as smooth as if you set false. If false a texel could lies between two pixels, being blended by the texture sampling mode you choose, the rendering result won't be as good, but very slow animation will be overall better looking. Default is true: content will be aligned.
          * - isVisible: true if the sprite must be visible, false for hidden. Default is true.
@@ -341,6 +314,7 @@
             x                     ?: number,
             y                     ?: number,
             rotation              ?: number,
+            size                  ?: Size,
             scale                 ?: number,
             scaleX                ?: number,
             scaleY                ?: number,
@@ -351,6 +325,7 @@
             spriteSize            ?: Size,
             spriteLocation        ?: Vector2,
             spriteScaleFactor     ?: Vector2,
+            scale9                ?: Vector4,
             invertY               ?: boolean,
             alignToPixel          ?: boolean,
             isVisible             ?: boolean,
@@ -381,31 +356,37 @@
             this.texture = texture;
             this.texture.wrapU = Texture.CLAMP_ADDRESSMODE;
             this.texture.wrapV = Texture.CLAMP_ADDRESSMODE;
-            this.size = (settings.spriteSize!=null) ? settings.spriteSize.clone() : null;
+            this._useSize = false;
+            this.spriteSize = (settings.spriteSize!=null) ? settings.spriteSize.clone() : null;
             this.spriteLocation = (settings.spriteLocation!=null) ? settings.spriteLocation.clone() : new Vector2(0, 0);
-            this.spriteScaleFactor = (settings.spriteScaleFactor!=null) ? settings.spriteScaleFactor : new Vector2(1, 1);
+            if (settings.size != null) {
+                this.size = settings.size;
+            }
             this.spriteFrame = 0;
             this.invertY = (settings.invertY == null) ? false : settings.invertY;
             this.alignToPixel = (settings.alignToPixel == null) ? true : settings.alignToPixel;
             this.useAlphaFromTexture = true;
+            this._scale9 = (settings.scale9 != null) ? settings.scale9.clone() : null;
 
             // If the user doesn't set a size, we'll use the texture's one, but if the texture is not loading, we HAVE to set a temporary dummy size otherwise the positioning engine will switch the marginAlignement to stretch/stretch, and WE DON'T WANT THAT.
             // The fucking delayed texture sprite bug is fixed!
             if (settings.spriteSize == null) {
-                this.size = new Size(10, 10);
+                this.spriteSize = new Size(10, 10);
             }
 
             if (settings.spriteSize == null || !texture.isReady()) {
                 if (texture.isReady()) {
                     let s = texture.getBaseSize();
-                    this.size = new Size(s.width, s.height);
+                    this.spriteSize = new Size(s.width, s.height);
+                    this._updateSpriteScaleFactor();
                 } else {
 
                     texture.onLoadObservable.add(() => {
                         if (settings.spriteSize == null) {
                             let s = texture.getBaseSize();
-                        this.size = new Size(s.width, s.height);
+                            this.spriteSize = new Size(s.width, s.height);
                         }
+                        this._updateSpriteScaleFactor();
                         this._positioningDirty();
                         this._setLayoutDirty();
                         this._instanceDirtyFlags |= Prim2DBase.originProperty.flagId | Sprite2D.textureProperty.flagId;  // To make sure the sprite is issued again for render
@@ -453,6 +434,18 @@
             return renderCache;
         }
 
+        protected getUsedShaderCategories(dataPart: InstanceDataBase): string[] {
+            var cat = super.getUsedShaderCategories(dataPart);
+
+            if (dataPart.id === Sprite2D.SPRITE2D_MAINPARTID) {
+                let useScale9 = this._scale9 != null;
+                if (useScale9) {
+                    cat.push(Sprite2D.SHAPE2D_CATEGORY_SCALE9);
+                }
+            }
+            return cat;
+        }
+
         protected createInstanceDataParts(): InstanceDataBase[] {
             return [new Sprite2DInstanceData(Sprite2D.SPRITE2D_MAINPARTID)];
         }
@@ -487,11 +480,14 @@
                     d.properties = Vector3.Zero();
                     d.textureSize = Vector2.Zero();
                     d.scaleFactor = Vector2.Zero();
+                    if (this.isScale9) {
+                        d.scale9 = Vector4.Zero();
+                    }
                 } else {
                     let ts = this.texture.getBaseSize();
+                    let ss = this.spriteSize;
                     let sl = this.spriteLocation;
-                    let ss = this.actualSize;
-                    let ssf = this.spriteScaleFactor;
+                    let ssf = this.actualScale;
                     d.topLeftUV = new Vector2(sl.x / ts.width, sl.y / ts.height);
                     let suv = new Vector2(ss.width / ts.width, ss.height / ts.height);
                     d.sizeUV = suv;
@@ -503,6 +499,12 @@
                     d.properties = Sprite2D._prop;
 
                     d.textureSize = new Vector2(ts.width, ts.height);
+
+                    let scale9 = this._scale9;
+                    if (scale9 != null) {
+                        let normalizedScale9 = new Vector4(scale9.x * suv.x / ss.width, scale9.y * suv.y / ss.height, scale9.z * suv.x / ss.width, scale9.w * suv.y / ss.height);
+                        d.scale9 = normalizedScale9;
+                    }
                 }
             }
             return true;
@@ -525,13 +527,81 @@
             return this.texture!=null && this.texture.hasAlpha && this.useAlphaFromTexture;
         }
 
+        private _updateSpriteScaleFactor() {
+            if (!this._useSize) {
+                return;
+            }
+
+            let sS = this.spriteSize;
+            let s = this.size;
+            if (s == null || sS == null) {
+                return;
+            }
+            this.scaleX = s.width / sS.width;
+            this.scaleY = s.height / sS.height;
+        }
+
         private _texture: Texture;
         private _oldTextureHasAlpha: boolean;
         private _useAlphaFromTexture: boolean;
-        private _location: Vector2;
-        private _spriteScaleFactor: Vector2;
+        private _useSize: boolean;
+        private _spriteLocation: Vector2;
+        private _spriteSize: Size;
         private _spriteFrame: number;
+        private _scale9: Vector4;
         private _invertY: boolean;
         private _alignToPixel: boolean;
     }
+
+    export class Sprite2DInstanceData extends InstanceDataBase {
+        constructor(partId: number) {
+            super(partId, 1);
+        }
+
+        @instanceData()
+        get topLeftUV(): Vector2 {
+            return null;
+        }
+        set topLeftUV(value: Vector2) {
+        }
+
+        @instanceData()
+        get sizeUV(): Vector2 {
+            return null;
+        }
+        set sizeUV(value: Vector2) {
+        }
+
+        @instanceData(Sprite2D.SHAPE2D_CATEGORY_SCALE9)
+        get scaleFactor(): Vector2 {
+            return null;
+        }
+        set scaleFactor(value: Vector2) {
+        }
+
+        @instanceData()
+        get textureSize(): Vector2 {
+            return null;
+        }
+        set textureSize(value: Vector2) {
+        }
+
+        // 3 floats being:
+        // - x: frame number to display
+        // - y: invertY setting
+        // - z: alignToPixel setting
+        @instanceData()
+        get properties(): Vector3 {
+            return null;
+        }
+        set properties(value: Vector3) {
+        }
+
+        @instanceData(Sprite2D.SHAPE2D_CATEGORY_SCALE9)
+        get scale9(): Vector4 {
+            return null;
+        }
+        set scale9(value: Vector4) {
+        }
+    }
 }

+ 14 - 6
canvas2D/src/Engine/babylon.text2d.ts

@@ -4,7 +4,7 @@
         vb: WebGLBuffer                                 = null;
         ib: WebGLBuffer                                 = null;
         instancingAttributes: InstancingAttributeInfo[] = null;
-        fontTexture: FontTexture                        = null;
+        fontTexture: BaseFontTexture                    = null;
         effect: Effect                                  = null;
         effectInstanced: Effect                         = null;
 
@@ -266,7 +266,7 @@
             return this._textSize;
         }
 
-        protected get fontTexture(): FontTexture {
+        protected get fontTexture(): BaseFontTexture {
             if (this._fontTexture) {
                 return this._fontTexture;
             }
@@ -356,6 +356,7 @@
             fontName                ?: string,
             fontSuperSample         ?: boolean,
             fontSignedDistanceField ?: boolean,
+            bitmapFontTexture       ?: BitmapFontTexture,
             defaultFontColor        ?: Color4,
             size                    ?: Size,
             tabulationSize          ?: number,
@@ -384,9 +385,16 @@
 
             super(settings);
 
-            this.fontName            = (settings.fontName==null) ? "12pt Arial" : settings.fontName;
-            this._fontSuperSample    = (settings.fontSuperSample!=null && settings.fontSuperSample);
-            this._fontSDF            = (settings.fontSignedDistanceField!=null && settings.fontSignedDistanceField);
+            if (settings.bitmapFontTexture != null) {
+                this._fontTexture     = settings.bitmapFontTexture;
+                this._fontName        = null;
+                this._fontSuperSample = false;
+                this._fontSDF         = false;
+            } else {
+                this._fontName       = (settings.fontName==null) ? "12pt Arial" : settings.fontName;
+                this._fontSuperSample= (settings.fontSuperSample!=null && settings.fontSuperSample);
+                this._fontSDF        = (settings.fontSignedDistanceField!=null && settings.fontSignedDistanceField);
+            }
             this.defaultFontColor    = (settings.defaultFontColor==null) ? new Color4(1,1,1,1) : settings.defaultFontColor;
             this._tabulationSize     = (settings.tabulationSize == null) ? 4 : settings.tabulationSize;
             this._textSize           = null;
@@ -547,7 +555,7 @@
             return !this._fontSDF;
         }
 
-        private _fontTexture: FontTexture;
+        private _fontTexture: BaseFontTexture;
         private _tabulationSize: number;
         private _charCount: number;
         private _fontName: string;

+ 51 - 1
canvas2D/src/shaders/sprite2d.fragment.fx

@@ -1,11 +1,61 @@
 varying vec2 vUV;
 varying float vOpacity;
+
+#ifdef Scale9
+varying vec2 vTopLeftUV;
+varying vec2 vBottomRightUV;
+varying vec4 vScale9;
+varying vec2 vScaleFactor;
+#endif
+
 uniform bool alphaTest;
 uniform sampler2D diffuseSampler;
 
 void main(void) {
-	vec4 color = texture2D(diffuseSampler, vUV);
+	
+	vec2 uv = vUV;
+
+#ifdef Scale9
+
+	vec2 sizeUV = vBottomRightUV - vTopLeftUV;
+
+	// Compute Horizontal (U) Coordinate
+	float leftPartUV = vTopLeftUV.x + (vScale9.x / vScaleFactor.x);
+	float rightPartUV = vTopLeftUV.x + sizeUV.x - ((sizeUV.x - vScale9.z) / vScaleFactor.x);
+
+	if (vUV.x < leftPartUV) {
+		uv.x = vTopLeftUV.x + ((vUV.x- vTopLeftUV.x) * vScaleFactor.x);
+	}
+
+	else if (vUV.x > rightPartUV) {
+		uv.x = vTopLeftUV.x + vScale9.z + ((vUV.x - rightPartUV) * vScaleFactor.x);
+	}
+
+	else {
+		float r = (vUV.x - leftPartUV) / (rightPartUV - leftPartUV);
+		uv.x = vTopLeftUV.x + vScale9.x + ((vScale9.z-vScale9.x) * r);
+	}
+
+	// Compute Vertical (V) Coordinate
+	float topPartUV = (vTopLeftUV.y + (vScale9.y / vScaleFactor.y));
+	float bottomPartUV = (vTopLeftUV.y + sizeUV.y - ((sizeUV.y - vScale9.w) / vScaleFactor.y));
+
+	if (vUV.y < topPartUV) {
+		uv.y = vTopLeftUV.y + ((vUV.y - vTopLeftUV.y) * vScaleFactor.y);
+	}
+
+	else if (vUV.y > bottomPartUV) {
+		uv.y = vTopLeftUV.y + vScale9.w + ((vUV.y - bottomPartUV) * vScaleFactor.y);
+	}
+
+	else {
+		float r = (vUV.y - topPartUV) / (bottomPartUV - topPartUV);
+		uv.y = vTopLeftUV.y + vScale9.y + ((vScale9.w - vScale9.y) * r);
+	}
+
+#endif
 
+	vec4 color = texture2D(diffuseSampler, uv);
 	if (alphaTest)
 	{
 		if (color.a < 0.95) {

+ 31 - 8
canvas2D/src/shaders/sprite2d.vertex.fx

@@ -10,12 +10,18 @@ attribute float index;
 
 att vec2 topLeftUV;
 att vec2 sizeUV;
+#ifdef Scale9
 att vec2 scaleFactor;
+#endif
 att vec2 textureSize;
 
 // x: frame, y: invertY, z: alignToPixel
 att vec3 properties;
 
+#ifdef Scale9
+att vec4 scale9;
+#endif
+
 att vec2 zBias;
 att vec4 transformX;
 att vec4 transformY;
@@ -27,14 +33,17 @@ att float opacity;
 varying vec2 vUV;
 varying float vOpacity;
 
+#ifdef Scale9
+varying vec2 vTopLeftUV;
+varying vec2 vBottomRightUV;
+varying vec4 vScale9;
+varying vec2 vScaleFactor;
+#endif
+
 void main(void) {
 
 	vec2 pos2;
 
-	//vec2 off = vec2(1.0 / textureSize.x, 1.0 / textureSize.y);
-	vec2 off = vec2(0.0, 0.0);
-	vec2 sfSizeUV = sizeUV * scaleFactor;
-
 	float frame = properties.x;
 	float invertY = properties.y;
 	float alignToPixel = properties.z;
@@ -42,25 +51,25 @@ void main(void) {
 	// Left/Top
 	if (index == 0.0) {
 		pos2 = vec2(0.0, 0.0);
-		vUV = vec2(topLeftUV.x + (frame*sfSizeUV.x) + off.x, topLeftUV.y - off.y);
+		vUV = vec2(topLeftUV.x + (frame*sizeUV.x), topLeftUV.y);
 	}
 
 	// Left/Bottom
 	else if (index == 1.0) {
 		pos2 = vec2(0.0,  1.0);
-		vUV = vec2(topLeftUV.x + (frame*sfSizeUV.x) + off.x, (topLeftUV.y + sfSizeUV.y));
+		vUV = vec2(topLeftUV.x + (frame*sizeUV.x), (topLeftUV.y + sizeUV.y));
 	}
 
 	// Right/Bottom
 	else if (index == 2.0) {
 		pos2 = vec2( 1.0,  1.0);
-		vUV = vec2(topLeftUV.x + sfSizeUV.x + (frame*sfSizeUV.x), (topLeftUV.y + sfSizeUV.y));
+		vUV = vec2(topLeftUV.x + sizeUV.x + (frame*sizeUV.x), (topLeftUV.y + sizeUV.y));
 	}
 
 	// Right/Top
 	else if (index == 3.0) {
 		pos2 = vec2( 1.0, 0.0);
-		vUV = vec2(topLeftUV.x + sfSizeUV.x + (frame*sfSizeUV.x), topLeftUV.y - off.y);
+		vUV = vec2(topLeftUV.x + sizeUV.x + (frame*sizeUV.x), topLeftUV.y);
 	}
 
 	if (invertY == 1.0) {
@@ -75,6 +84,20 @@ void main(void) {
 		pos.xy = pos2.xy * sizeUV * textureSize;
 	}
 
+#ifdef Scale9
+	if (invertY == 1.0) {
+		vTopLeftUV = vec2(topLeftUV.x, 1.0 - (topLeftUV.y + sizeUV.y));
+		vBottomRightUV = vec2(topLeftUV.x + sizeUV.x, 1.0 - topLeftUV.y);
+		vScale9 = vec4(scale9.x, sizeUV.y - scale9.w, scale9.z, sizeUV.y - scale9.y);
+	}
+	else {
+		vTopLeftUV = topLeftUV;
+		vBottomRightUV = vec2(topLeftUV.x, topLeftUV.y + sizeUV.y);
+		vScale9 = scale9;
+	}
+	vScaleFactor = scaleFactor;
+#endif
+
 	vOpacity = opacity;
 	pos.z = 1.0;
 	pos.w = 1.0;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 25 - 25
dist/preview release/babylon.core.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2402 - 2394
dist/preview release/babylon.d.ts


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 36 - 36
dist/preview release/babylon.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 633 - 812
dist/preview release/babylon.max.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 35 - 35
dist/preview release/babylon.noworker.js


+ 383 - 22
dist/preview release/canvas2D/babylon.canvas2d.d.ts

@@ -415,6 +415,196 @@ declare module BABYLON {
 
 declare module BABYLON {
     /**
+     * This class given information about a given character.
+     */
+    class CharInfo {
+        /**
+         * The normalized ([0;1]) top/left position of the character in the texture
+         */
+        topLeftUV: Vector2;
+        /**
+         * The normalized ([0;1]) right/bottom position of the character in the texture
+         */
+        bottomRightUV: Vector2;
+        charWidth: number;
+    }
+    /**
+     * This is an abstract base class to hold a Texture that will contain a FontMap
+     */
+    abstract class BaseFontTexture extends Texture {
+        constructor(url: string, scene: Scene, noMipmap?: boolean, invertY?: boolean, samplingMode?: number);
+        /**
+         * Is the Font is using Super Sampling (each font texel is doubled).
+         */
+        readonly isSuperSampled: boolean;
+        /**
+         * Is the Font was rendered using the Signed Distance Field algorithm
+         * @returns {}
+         */
+        readonly isSignedDistanceField: boolean;
+        /**
+         * Get the Width (in pixel) of the Space character
+         */
+        readonly spaceWidth: number;
+        /**
+         * Get the Line height (in pixel)
+         */
+        readonly lineHeight: number;
+        /**
+         * When the FontTexture is retrieved through the FontCache, there's a reference counter that is incremented for each use.
+         * You also have the possibility to extend the lifetime of the FontTexture when passing it to another object by calling this method
+         * Don't forget to call the corresponding decCachedFontTextureCounter method when you no longer have use of the FontTexture.
+         * Each call to incCachedFontTextureCounter must have a corresponding call to decCachedFontTextureCounter.
+         */
+        abstract incCachedFontTextureCounter(): any;
+        /**
+         * Decrement the reference counter, if it reaches 0 the FontTexture is disposed
+         */
+        abstract decCachedFontTextureCounter(): any;
+        /**
+         * Is the font dynamically updated, if true is returned then you have to call the update() before using the font in rendering if new character were adding using getChar()
+         */
+        readonly abstract isDynamicFontTexture: boolean;
+        /**
+         * Will fetch the new characters retrieved with getChar() to the texture.
+         * If there were no new char, this call is harmless and quit in no time.
+         * If there were new chars a texture lock/update is made, which is a costy operation.
+         */
+        abstract update(): void;
+        /**
+         * Measure the width/height that will take a given text
+         * @param text the text to measure
+         * @param tabulationSize the size (in space character) of the tabulation character, default value must be 4
+         */
+        measureText(text: string, tabulationSize?: number): Size;
+        /**
+         * Retrieve the CharInfo object for a given character
+         * @param char the character to retrieve the CharInfo object from (e.g.: "A", "a", etc.)
+         */
+        abstract getChar(char: string): CharInfo;
+        protected _charInfos: StringDictionary<CharInfo>;
+        protected _lineHeight: number;
+        protected _spaceWidth: any;
+        protected _superSample: boolean;
+        protected _signedDistanceField: boolean;
+        protected _cachedFontId: string;
+    }
+    class BitmapFontInfo {
+        kerningDic: StringDictionary<number>;
+        charDic: StringDictionary<CharInfo>;
+        textureSize: Size;
+        atlasName: string;
+        padding: Vector4;
+        lineHeight: number;
+        textureUrl: string;
+        textureFile: string;
+    }
+    interface IBitmapFontLoader {
+        loadFont(fontDataContent: any, scene: Scene, invertY: boolean): {
+            bfi: BitmapFontInfo;
+            errorMsg: string;
+            errorCode: number;
+        };
+    }
+    class BitmapFontTexture extends BaseFontTexture {
+        constructor(scene: Scene, bmFontUrl: string, textureUrl?: string, noMipmap?: boolean, invertY?: boolean, samplingMode?: number, onLoad?: () => void, onError?: (msg: string, code: number) => void);
+        static GetCachedFontTexture(scene: Scene, fontTexture: BitmapFontTexture): BitmapFontTexture;
+        static ReleaseCachedFontTexture(scene: Scene, fontTexture: BitmapFontTexture): void;
+        /**
+         * Is the font dynamically updated, if true is returned then you have to call the update() before using the font in rendering if new character were adding using getChar()
+         */
+        readonly isDynamicFontTexture: boolean;
+        /**
+         * This method does nothing for a BitmapFontTexture object as it's a static texture
+         */
+        update(): void;
+        /**
+         * Retrieve the CharInfo object for a given character
+         * @param char the character to retrieve the CharInfo object from (e.g.: "A", "a", etc.)
+         */
+        getChar(char: string): CharInfo;
+        /**
+         * For FontTexture retrieved using GetCachedFontTexture, use this method when you transfer this object's lifetime to another party in order to share this resource.
+         * When the other party is done with this object, decCachedFontTextureCounter must be called.
+         */
+        incCachedFontTextureCounter(): void;
+        /**
+         * Use this method only in conjunction with incCachedFontTextureCounter, call it when you no longer need to use this shared resource.
+         */
+        decCachedFontTextureCounter(): void;
+        private _usedCounter;
+        static addLoader(fileExtension: string, plugin: IBitmapFontLoader): void;
+        static plugins: StringDictionary<IBitmapFontLoader[]>;
+    }
+    /**
+     * This class is a special kind of texture which generates on the fly characters of a given css style "fontName".
+     * The generated texture will be updated when new characters will be retrieved using the getChar() method, but you have
+     *  to call the update() method for the texture to fetch these changes, you can harmlessly call update any time you want, if no
+     *  change were made, nothing will happen.
+     * The Font Texture can be rendered in three modes: normal size, super sampled size (x2) or using Signed Distance Field rendering.
+     * Signed Distance Field should be prefered because the texture can be rendered using AlphaTest instead of Transparency, which is way more faster. More about SDF here (http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf).
+     * The only flaw of SDF is that the rendering quality may not be the best or the edges too sharp is the font thickness is too thin.
+     */
+    class FontTexture extends BaseFontTexture {
+        private _canvas;
+        private _context;
+        private _lineHeightSuper;
+        private _xMargin;
+        private _yMargin;
+        private _offset;
+        private _currentFreePosition;
+        private _curCharCount;
+        private _lastUpdateCharCount;
+        private _spaceWidthSuper;
+        private _sdfCanvas;
+        private _sdfContext;
+        private _sdfScale;
+        private _usedCounter;
+        readonly isDynamicFontTexture: boolean;
+        static GetCachedFontTexture(scene: Scene, fontName: string, supersample?: boolean, signedDistanceField?: boolean): FontTexture;
+        static ReleaseCachedFontTexture(scene: Scene, fontName: string, supersample?: boolean, signedDistanceField?: boolean): void;
+        /**
+         * Create a new instance of the FontTexture class
+         * @param name the name of the texture
+         * @param font the font to use, use the W3C CSS notation
+         * @param scene the scene that owns the texture
+         * @param maxCharCount the approximative maximum count of characters that could fit in the texture. This is an approximation because most of the fonts are proportional (each char has its own Width). The 'W' character's width is used to compute the size of the texture based on the given maxCharCount
+         * @param samplingMode the texture sampling mode
+         * @param superSample if true the FontTexture will be created with a font of a size twice bigger than the given one but all properties (lineHeight, charWidth, etc.) will be according to the original size. This is made to improve the text quality.
+         */
+        constructor(name: string, font: string, scene: Scene, maxCharCount?: number, samplingMode?: number, superSample?: boolean, signedDistanceField?: boolean);
+        /**
+         * Make sure the given char is present in the font map.
+         * @param char the character to get or add
+         * @return the CharInfo instance corresponding to the given character
+         */
+        getChar(char: string): CharInfo;
+        private _computeSDFChar(source);
+        private getSuperSampleFont(font);
+        private getFontHeight(font);
+        readonly canRescale: boolean;
+        getContext(): CanvasRenderingContext2D;
+        /**
+         * Call this method when you've call getChar() at least one time, this will update the texture if needed.
+         * Don't be afraid to call it, if no new character was added, this method simply does nothing.
+         */
+        update(): void;
+        clone(): FontTexture;
+        /**
+         * For FontTexture retrieved using GetCachedFontTexture, use this method when you transfer this object's lifetime to another party in order to share this resource.
+         * When the other party is done with this object, decCachedFontTextureCounter must be called.
+         */
+        incCachedFontTextureCounter(): void;
+        /**
+         * Use this method only in conjunction with incCachedFontTextureCounter, call it when you no longer need to use this shared resource.
+         */
+        decCachedFontTextureCounter(): void;
+    }
+    function BitmapFontLoaderPlugin(fileExtension: string, plugin: IBitmapFontLoader): (target: Object) => void;
+}
+
+declare module BABYLON {
+    /**
      * Stores 2D Bounding Information.
      * This class handles a circle area and a bounding rectangle one.
      */
@@ -1674,6 +1864,8 @@ declare module BABYLON {
          * Use this property to set a new Size object, otherwise to change only the width/height use Prim2DBase.width or height properties.
          */
         size: Size;
+        protected internalGetSize(): Size;
+        protected internalSetSize(value: Size): void;
         /**
          * Direct access to the size.width value of the primitive
          * Use this property when you only want to change one component of the size property
@@ -2728,36 +2920,26 @@ declare module BABYLON {
         render(instanceInfo: GroupInstanceInfo, context: Render2DContext): boolean;
         dispose(): boolean;
     }
-    class Sprite2DInstanceData extends InstanceDataBase {
-        constructor(partId: number);
-        topLeftUV: Vector2;
-        sizeUV: Vector2;
-        scaleFactor: Vector2;
-        textureSize: Vector2;
-        properties: Vector3;
-    }
     class Sprite2D extends RenderablePrim2D {
         static SPRITE2D_MAINPARTID: number;
+        static SHAPE2D_CATEGORY_SCALE9: string;
         static textureProperty: Prim2DPropInfo;
         static useAlphaFromTextureProperty: Prim2DPropInfo;
         static actualSizeProperty: Prim2DPropInfo;
+        static spriteSizeProperty: Prim2DPropInfo;
         static spriteLocationProperty: Prim2DPropInfo;
         static spriteFrameProperty: Prim2DPropInfo;
         static invertYProperty: Prim2DPropInfo;
-        static spriteScaleFactorProperty: Prim2DPropInfo;
+        static spriteScale9Property: Prim2DPropInfo;
         texture: Texture;
         useAlphaFromTexture: boolean;
+        size: Size;
         actualSize: Size;
+        spriteSize: Size;
         spriteLocation: Vector2;
         spriteFrame: number;
         invertY: boolean;
-        spriteScaleFactor: Vector2;
-        /**
-         * Sets the scale of the sprite using a BABYLON.Size(w,h).
-         * Keeps proportion by taking the maximum of the two scale for x and y.
-         * @param {Size} size Size(width,height)
-         */
-        scaleToSize(size: Size): void;
+        readonly isScale9: boolean;
         /**
          * Get/set if the sprite rendering should be aligned to the target rendering device pixel or not
          */
@@ -2768,6 +2950,7 @@ declare module BABYLON {
          */
         getAnimatables(): IAnimatable[];
         protected levelIntersect(intersectInfo: IntersectInfo2D): boolean;
+        readonly isSizeAuto: boolean;
         /**
          * Create an 2D Sprite primitive
          * @param texture the texture that stores the sprite to render
@@ -2778,13 +2961,15 @@ declare module BABYLON {
          * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
          * - rotation: the initial rotation (in radian) of the primitive. default is 0
          * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
+         * - size: the size of the sprite displayed in the canvas, if not specified the spriteSize will be used
          * - dontInheritParentScale: if set the parent's scale won't be taken into consideration to compute the actualScale property
          * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
          * - zOrder: override the zOrder with the specified value
          * - origin: define the normalized origin point location, default [0.5;0.5]
-         * - spriteSize: the size of the sprite (in pixels), if null the size of the given texture will be used, default is null.
+         * - spriteSize: the size of the sprite (in pixels) as it is stored in the texture, if null the size of the given texture will be used, default is null.
          * - spriteLocation: the location (in pixels) in the texture of the top/left corner of the Sprite to display, default is null (0,0)
-         * - spriteScaleFactor: say you want to display a sprite twice as big as its bitmap which is 64,64, you set the spriteSize to 128,128 and have to set the spriteScaleFactory to 0.5,0.5 in order to address only the 64,64 pixels of the bitmaps. Default is 1,1.
+         * - spriteScaleFactor: DEPRECATED. Old behavior: say you want to display a sprite twice as big as its bitmap which is 64,64, you set the spriteSize to 128,128 and have to set the spriteScaleFactory to 0.5,0.5 in order to address only the 64,64 pixels of the bitmaps. Default is 1,1.
+         * - scale9: draw the sprite as a Scale9 sprite, see http://yannickloriot.com/2013/03/9-patch-technique-in-cocos2d/ for more info. x, y, w, z are left, bottom, right, top coordinate of the resizable box
          * - invertY: if true the texture Y will be inverted, default is false.
          * - alignToPixel: if true the sprite's texels will be aligned to the rendering viewport pixels, ensuring the best rendering quality but slow animations won't be done as smooth as if you set false. If false a texel could lies between two pixels, being blended by the texture sampling mode you choose, the rendering result won't be as good, but very slow animation will be overall better looking. Default is true: content will be aligned.
          * - isVisible: true if the sprite must be visible, false for hidden. Default is true.
@@ -2813,6 +2998,7 @@ declare module BABYLON {
             x?: number;
             y?: number;
             rotation?: number;
+            size?: Size;
             scale?: number;
             scaleX?: number;
             scaleY?: number;
@@ -2823,6 +3009,7 @@ declare module BABYLON {
             spriteSize?: Size;
             spriteLocation?: Vector2;
             spriteScaleFactor?: Vector2;
+            scale9?: Vector4;
             invertY?: boolean;
             alignToPixel?: boolean;
             isVisible?: boolean;
@@ -2845,6 +3032,7 @@ declare module BABYLON {
         });
         protected createModelRenderCache(modelKey: string): ModelRenderCache;
         protected setupModelRenderCache(modelRenderCache: ModelRenderCache): Sprite2DRenderCache;
+        protected getUsedShaderCategories(dataPart: InstanceDataBase): string[];
         protected createInstanceDataParts(): InstanceDataBase[];
         private static _prop;
         private static layoutConstructMode;
@@ -2854,15 +3042,187 @@ declare module BABYLON {
         protected _mustUpdateInstance(): boolean;
         protected _useTextureAlpha(): boolean;
         protected _shouldUseAlphaFromTexture(): boolean;
+        private _updateSpriteScaleFactor();
         private _texture;
         private _oldTextureHasAlpha;
         private _useAlphaFromTexture;
-        private _location;
-        private _spriteScaleFactor;
+        private _useSize;
+        private _spriteLocation;
+        private _spriteSize;
         private _spriteFrame;
+        private _scale9;
         private _invertY;
         private _alignToPixel;
     }
+    class Sprite2DInstanceData extends InstanceDataBase {
+        constructor(partId: number);
+        topLeftUV: Vector2;
+        sizeUV: Vector2;
+        scaleFactor: Vector2;
+        textureSize: Vector2;
+        properties: Vector3;
+        scale9: Vector4;
+    }
+}
+
+declare module BABYLON {
+    /**
+     * Interface to create your own Loader of Atlas Data file.
+     * Call the AtlasPictureInfoFactory.addLoader to addd your loader instance
+     */
+    interface IAtlasLoader {
+        loadFile(content: any): {
+            api: AtlasPictureInfo;
+            errorMsg: string;
+            errorCode: number;
+        };
+    }
+    /**
+     * This class will contains information about a sub picture present in an Atlas Picture.
+     */
+    class AtlasSubPictureInfo {
+        /**
+         * Name of the SubPicture, generally the filename of the initial picture file.
+         */
+        name: string;
+        /**
+         * Location of the bottom/left corner of the sub picture from the bottom/left corner the Atlas Picture
+         */
+        location: Vector2;
+        /**
+         * Size in pixel of the sub picture
+         */
+        size: Size;
+    }
+    /**
+     * This class represent an Atlas Picture, it contains the information of all the sub pictures and the Texture that stores the bitmap.
+     * You get an instance of this class using methods of the AtlasPictureInfoFactory
+     */
+    class AtlasPictureInfo {
+        /**
+         * Creates many sprite from the Atlas Picture
+         * @param filterCallback a predicate if true is returned then the corresponding sub picture will be used to create a sprite.
+         * The Predicate has many parameters:
+         *  - index: just an index incremented at each sub picture submitted for Sprite creation
+         *  - name: the sub picture's name
+         *  - aspi: the AtlasSubPictureInfo corresponding to the submitted sub picture
+         *  - settings: the Sprite2D creation settings, you can alter this JSON object but BEWARE, the alterations will be kept for subsequent Sprite2D creations!
+         * @param spriteSettings The Sprite2D settings to use for Sprite creation, this JSON object will be passed to the filterCallback for you to alter it, if needed.
+         */
+        createSprites(filterCallback: (index: number, name: string, aspi: AtlasSubPictureInfo, settings: any) => boolean, spriteSettings: {
+            parent?: Prim2DBase;
+            position?: Vector2;
+            x?: number;
+            y?: number;
+            rotation?: number;
+            size?: Size;
+            scale?: number;
+            scaleX?: number;
+            scaleY?: number;
+            dontInheritParentScale?: boolean;
+            opacity?: number;
+            zOrder?: number;
+            origin?: Vector2;
+            scale9?: Vector4;
+            invertY?: boolean;
+            alignToPixel?: boolean;
+            isVisible?: boolean;
+            isPickable?: boolean;
+            isContainer?: boolean;
+            childrenFlatZOrder?: boolean;
+            marginTop?: number | string;
+            marginLeft?: number | string;
+            marginRight?: number | string;
+            marginBottom?: number | string;
+            margin?: number | string;
+            marginHAlignment?: number;
+            marginVAlignment?: number;
+            marginAlignment?: string;
+            paddingTop?: number | string;
+            paddingLeft?: number | string;
+            paddingRight?: number | string;
+            paddingBottom?: number | string;
+            padding?: string;
+        }): Array<Sprite2D>;
+        /**
+         * Create one Sprite from a sub picture
+         * @param subPictureName the name of the sub picture to use
+         * @param spriteSettings the Sprite2D settings to use for the Sprite instance creation
+         */
+        createSprite(subPictureName: string, spriteSettings: {
+            parent?: Prim2DBase;
+            position?: Vector2;
+            x?: number;
+            y?: number;
+            rotation?: number;
+            size?: Size;
+            scale?: number;
+            scaleX?: number;
+            scaleY?: number;
+            dontInheritParentScale?: boolean;
+            opacity?: number;
+            zOrder?: number;
+            origin?: Vector2;
+            scale9?: Vector4;
+            invertY?: boolean;
+            alignToPixel?: boolean;
+            isVisible?: boolean;
+            isPickable?: boolean;
+            isContainer?: boolean;
+            childrenFlatZOrder?: boolean;
+            marginTop?: number | string;
+            marginLeft?: number | string;
+            marginRight?: number | string;
+            marginBottom?: number | string;
+            margin?: number | string;
+            marginHAlignment?: number;
+            marginVAlignment?: number;
+            marginAlignment?: string;
+            paddingTop?: number | string;
+            paddingLeft?: number | string;
+            paddingRight?: number | string;
+            paddingBottom?: number | string;
+            padding?: string;
+        }): Sprite2D;
+        /**
+         * Size of the Atlas Picture
+         */
+        atlasSize: Size;
+        /**
+         * String Dictionary of all the sub pictures, the key is the sub picture's name, the value is the info object
+         */
+        subPictures: StringDictionary<AtlasSubPictureInfo>;
+        /**
+         * The Texture associated to the Atlas Picture info
+         */
+        texture: Texture;
+    }
+    /**
+     * This if the Factory class containing static method to create Atlas Pictures Info objects or add new loaders
+     */
+    class AtlasPictureInfoFactory {
+        /**
+         * Add a custom loader
+         * @param fileExtension must be the file extension (without the dot) of the file that is loaded by this loader (e.g.: json)
+         * @param plugin the instance of the loader
+         */
+        static addLoader(fileExtension: string, plugin: IAtlasLoader): void;
+        /**
+         * Load an Atlas Picture Info object from a data file at a given url and with a given texture
+         * @param texture the texture containing the atlas bitmap
+         * @param url the URL of the Atlas Info data file
+         * @param onLoad a callback that will be called when the AtlasPictureInfo object will be loaded and ready
+         * @param onError a callback that will be called in case of error
+         */
+        static loadFromUrl(texture: Texture, url: string, onLoad: (api: AtlasPictureInfo) => void, onError?: (msg: string, code: number) => void): any;
+        private static plugins;
+    }
+    /**
+     * Use this decorator when you declare an Atlas Loader Class for the loader to register itself automatically.
+     * @param fileExtension the extension of the file that the plugin is loading (there can be many plugin for the same extension)
+     * @param plugin an instance of the plugin class to add to the AtlasPictureInfoFactory
+     */
+    function AtlasLoaderPlugin(fileExtension: string, plugin: IAtlasLoader): (target: Object) => void;
 }
 
 declare module BABYLON {
@@ -2871,7 +3231,7 @@ declare module BABYLON {
         vb: WebGLBuffer;
         ib: WebGLBuffer;
         instancingAttributes: InstancingAttributeInfo[];
-        fontTexture: FontTexture;
+        fontTexture: BaseFontTexture;
         effect: Effect;
         effectInstanced: Effect;
         render(instanceInfo: GroupInstanceInfo, context: Render2DContext): boolean;
@@ -2909,7 +3269,7 @@ declare module BABYLON {
          * Get the area that bounds the text associated to the primitive
          */
         readonly textSize: Size;
-        protected readonly fontTexture: FontTexture;
+        protected readonly fontTexture: BaseFontTexture;
         /**
          * Dispose the primitive, remove it from its parent
          */
@@ -2971,6 +3331,7 @@ declare module BABYLON {
             fontName?: string;
             fontSuperSample?: boolean;
             fontSignedDistanceField?: boolean;
+            bitmapFontTexture?: BitmapFontTexture;
             defaultFontColor?: Color4;
             size?: Size;
             tabulationSize?: number;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1284 - 145
dist/preview release/canvas2D/babylon.canvas2d.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 10 - 10
dist/preview release/canvas2D/babylon.canvas2d.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2 - 2
dist/preview release/inspector/babylon.inspector.bundle.js


+ 7 - 1
dist/preview release/inspector/babylon.inspector.js

@@ -2866,6 +2866,12 @@ var INSPECTOR;
                     elem: elemValue,
                     updateFct: function () { return (_this._engine.getCaps().drawBuffersExtension ? "Yes" : "No"); }
                 });
+                elemLabel = _this._createStatLabel("Vertex array object", _this._panel);
+                elemValue = INSPECTOR.Helpers.CreateDiv('stat-value', _this._panel);
+                _this._updatableProperties.push({
+                    elem: elemValue,
+                    updateFct: function () { return (_this._engine.getCaps().vertexArrayObject ? "Yes" : "No"); }
+                });
             }
             title = INSPECTOR.Helpers.CreateDiv('stat-title2', _this._panel);
             title.textContent = "Caps.";
@@ -2901,7 +2907,7 @@ var INSPECTOR;
                 var elemValue = INSPECTOR.Helpers.CreateDiv('stat-infos', _this._panel);
                 _this._updatableProperties.push({
                     elem: elemValue,
-                    updateFct: function () { return _this._engine.webGLVersion + " - " + _this._glInfo.version + " - " + _this._glInfo.renderer; }
+                    updateFct: function () { return "WebGL v" + _this._engine.webGLVersion + " - " + _this._glInfo.version + " - " + _this._glInfo.renderer; }
                 });
             }
             // Register the update loop

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2 - 2
dist/preview release/inspector/babylon.inspector.min.js


+ 3 - 1
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -287,8 +287,10 @@ declare module BABYLON {
         materials: Object;
         animations: Object;
         skins: Object;
-        currentScene: Object;
+        currentScene?: Object;
+        scenes: Object;
         extensionsUsed: string[];
+        extensionsRequired?: string[];
         buffersCount: number;
         shaderscount: number;
         scene: Scene;

+ 72 - 42
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -233,13 +233,24 @@ var BABYLON;
                 if (!sampler) {
                     continue;
                 }
-                var inputData = animation.parameters[sampler.input];
-                var outputData = animation.parameters[sampler.output];
+                var inputData = null;
+                var outputData = null;
+                if (animation.parameters) {
+                    inputData = animation.parameters[sampler.input];
+                    outputData = animation.parameters[sampler.output];
+                }
+                else {
+                    inputData = sampler.input;
+                    outputData = sampler.output;
+                }
                 var bufferInput = BABYLON.GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[inputData]);
                 var bufferOutput = BABYLON.GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[outputData]);
                 var targetID = channel.target.id;
                 var targetNode = gltfRuntime.scene.getNodeByID(targetID);
                 if (targetNode === null) {
+                    targetNode = gltfRuntime.scene.getNodeByName(targetID);
+                }
+                if (targetNode === null) {
                     BABYLON.Tools.Warn("Creating animation named " + anim + ". But cannot find node named " + targetID + " to attach to");
                     continue;
                 }
@@ -336,10 +347,10 @@ var BABYLON;
     */
     var configureBoneTransformation = function (node) {
         var mat = null;
-        if (node.translation && node.rotation && node.scale) {
-            var scale = BABYLON.Vector3.FromArray(node.scale);
-            var rotation = BABYLON.Quaternion.FromArray(node.rotation);
-            var position = BABYLON.Vector3.FromArray(node.translation);
+        if (node.translation || node.rotation || node.scale) {
+            var scale = BABYLON.Vector3.FromArray(node.scale || [1, 1, 1]);
+            var rotation = BABYLON.Quaternion.FromArray(node.rotation || [0, 0, 0, 1]);
+            var position = BABYLON.Vector3.FromArray(node.translation || [0, 0, 0]);
             // Y is Up
             if (GLTFFileLoader.MakeYUP) {
                 rotation = rotation.multiply(new BABYLON.Quaternion(-0.707107, 0, 0, 0.707107));
@@ -357,7 +368,7 @@ var BABYLON;
     var getParentBone = function (gltfRuntime, skins, jointName, newSkeleton) {
         // Try to find
         for (var i = 0; i < newSkeleton.bones.length; i++) {
-            if (newSkeleton.bones[i].id === jointName) {
+            if (newSkeleton.bones[i].name === jointName) {
                 return newSkeleton.bones[i];
             }
         }
@@ -512,18 +523,8 @@ var BABYLON;
                 newSkeleton.bones.push(existingBone);
                 continue;
             }
-            // Check if node already exists
-            var foundBone = false;
-            for (var j = 0; j < newSkeleton.bones.length; j++) {
-                if (newSkeleton.bones[j].id === id) {
-                    foundBone = true;
-                    break;
-                }
-            }
-            if (foundBone) {
-                continue;
-            }
             // Search for parent bone
+            var foundBone = false;
             var parentBone = null;
             for (var j = 0; j < i; j++) {
                 var joint = getJointNode(gltfRuntime, skins.jointNames[j]).node;
@@ -559,7 +560,7 @@ var BABYLON;
                 var invertMesh = BABYLON.Matrix.Invert(mesh.getWorldMatrix());
                 mat = mat.multiply(mesh.getWorldMatrix());
             }
-            var bone = new BABYLON.Bone(node.name, newSkeleton, parentBone, mat);
+            var bone = new BABYLON.Bone(node.jointName, newSkeleton, parentBone, mat);
             bone.id = id;
         }
         // Polish
@@ -577,8 +578,8 @@ var BABYLON;
                 }
             }
         }
-        // Finish
         newSkeleton.prepare();
+        // Finish
         for (var i = 0; i < nodesToRootToAdd.length; i++) {
             newSkeleton.bones.push(nodesToRootToAdd[i]);
         }
@@ -775,7 +776,6 @@ var BABYLON;
                     }
                 }
                 if (newMesh.skeleton !== null) {
-                    newMesh.useBones = true;
                 }
                 lastNode = newMesh;
             }
@@ -911,8 +911,10 @@ var BABYLON;
                 newNode.parent = parent;
             }
         }
-        for (var i = 0; i < node.children.length; i++) {
-            traverseNodes(gltfRuntime, node.children[i], newNode, meshIncluded);
+        if (node.children) {
+            for (var i = 0; i < node.children.length; i++) {
+                traverseNodes(gltfRuntime, node.children[i], newNode, meshIncluded);
+            }
         }
     };
     /**
@@ -921,8 +923,18 @@ var BABYLON;
     var postLoad = function (gltfRuntime) {
         // Nodes
         var currentScene = gltfRuntime.currentScene;
-        for (var i = 0; i < currentScene.nodes.length; i++) {
-            traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+        if (currentScene) {
+            for (var i = 0; i < currentScene.nodes.length; i++) {
+                traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+            }
+        }
+        else {
+            for (var thing in gltfRuntime.scenes) {
+                currentScene = gltfRuntime.scenes[thing];
+                for (var i = 0; i < currentScene.nodes.length; i++) {
+                    traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+                }
+            }
         }
         // Set animations
         loadAnimations(gltfRuntime);
@@ -935,6 +947,7 @@ var BABYLON;
     * onBind shaderrs callback to set uniforms and matrices
     */
     var onBindShaderMaterial = function (mesh, gltfRuntime, unTreatedUniforms, shaderMaterial, technique, material, onSuccess) {
+        var materialValues = material.values || technique.parameters;
         for (var unif in unTreatedUniforms) {
             var uniform = unTreatedUniforms[unif];
             var type = uniform.type;
@@ -954,13 +967,13 @@ var BABYLON;
                 }
             }
             else {
-                var value = material.values[technique.uniforms[unif]];
+                var value = materialValues[technique.uniforms[unif]];
                 if (!value) {
                     continue;
                 }
                 if (type === BABYLON.EParameterType.SAMPLER_2D) {
-                    var texture = gltfRuntime.textures[value].babylonTexture;
-                    if (texture === null) {
+                    var texture = gltfRuntime.textures[material.values ? value : uniform.value].babylonTexture;
+                    if (texture === null || texture === undefined) {
                         continue;
                     }
                     shaderMaterial.getEffect().setTexture(unif, texture);
@@ -977,7 +990,7 @@ var BABYLON;
     * Loads the appropriate textures
     */
     var prepareShaderMaterialUniforms = function (gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms) {
-        var materialValues = material.values;
+        var materialValues = material.values || technique.parameters;
         var techniqueUniforms = technique.uniforms;
         /**
         * Prepare values here (not matrices)
@@ -993,19 +1006,21 @@ var BABYLON;
             if (!value) {
                 continue;
             }
-            var onLoadTexture = function (texture) {
-                if (uniform.value) {
-                    // Static uniform
-                    shaderMaterial.setTexture(unif, texture);
-                    delete unTreatedUniforms[unif];
-                }
+            var onLoadTexture = function (uniformName) {
+                return function (texture) {
+                    if (uniform.value) {
+                        // Static uniform
+                        shaderMaterial.setTexture(uniformName, texture);
+                        delete unTreatedUniforms[uniformName];
+                    }
+                };
             };
             // Texture (sampler2D)
             if (type === BABYLON.EParameterType.SAMPLER_2D) {
-                BABYLON.GLTFFileLoaderExtension.LoadTextureAsync(gltfRuntime, value, onLoadTexture, function () { return onLoadTexture(null); });
+                BABYLON.GLTFFileLoaderExtension.LoadTextureAsync(gltfRuntime, material.values ? value : uniform.value, onLoadTexture(unif), function () { return onLoadTexture(null); });
             }
             else {
-                if (uniform.value && BABYLON.GLTFUtils.SetUniform(shaderMaterial, unif, value, type)) {
+                if (uniform.value && BABYLON.GLTFUtils.SetUniform(shaderMaterial, unif, material.values ? value : uniform.value, type)) {
                     // Static uniform
                     delete unTreatedUniforms[unif];
                 }
@@ -1085,8 +1100,8 @@ var BABYLON;
                 materials: {},
                 animations: {},
                 skins: {},
-                currentScene: {},
                 extensionsUsed: [],
+                scenes: {},
                 buffersCount: 0,
                 shaderscount: 0,
                 scene: scene,
@@ -1149,6 +1164,9 @@ var BABYLON;
             if (parsedData.skins) {
                 parseObject(parsedData.skins, "skins", gltfRuntime);
             }
+            if (parsedData.scenes) {
+                gltfRuntime.scenes = parsedData.scenes;
+            }
             if (parsedData.scene && parsedData.scenes) {
                 gltfRuntime.currentScene = parsedData.scenes[parsedData.scene];
             }
@@ -1304,7 +1322,7 @@ var BABYLON;
                 attributes: attributes,
                 uniforms: uniforms,
                 samplers: samplers,
-                needAlphaBlending: states.functions && states.functions.blendEquationSeparate
+                needAlphaBlending: states && states.enable && states.enable.indexOf(3042) !== -1
             };
             BABYLON.Effect.ShadersStore[program.vertexShader + id + "VertexShader"] = newVertexShader;
             BABYLON.Effect.ShadersStore[program.fragmentShader + id + "PixelShader"] = newPixelShader;
@@ -1312,7 +1330,7 @@ var BABYLON;
             shaderMaterial.onError = onShaderCompileError(program, shaderMaterial, onError);
             shaderMaterial.onCompiled = onShaderCompileSuccess(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms, onSuccess);
             shaderMaterial.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation;
-            if (states.functions) {
+            if (states && states.functions) {
                 var functions = states.functions;
                 if (functions.cullFace && functions.cullFace[0] !== BABYLON.ECullingType.BACK) {
                     shaderMaterial.backFaceCulling = false;
@@ -1499,8 +1517,20 @@ var BABYLON;
         // Creates nodes before loading buffers and shaders
         GLTFFileLoader.prototype._createNodes = function (gltfRuntime) {
             var currentScene = gltfRuntime.currentScene;
-            for (var i = 0; i < currentScene.nodes.length; i++) {
-                traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+            if (currentScene) {
+                // Only one scene even if multiple scenes are defined
+                for (var i = 0; i < currentScene.nodes.length; i++) {
+                    traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+                }
+            }
+            else {
+                // Load all scenes
+                for (var thing in gltfRuntime.scenes) {
+                    currentScene = gltfRuntime.scenes[thing];
+                    for (var i = 0; i < currentScene.nodes.length; i++) {
+                        traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+                    }
+                }
             }
         };
         return GLTFFileLoader;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


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

@@ -1,14 +1,30 @@
 # 2.6.0:
 
 ### Major updates
+ - WebGL2 context support.WebGL2 is initialized instead of WebGL 1 when available ([deltakosh](https://github.com/deltakosh))
+ - Support for [Vertex Array Objects](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt) ([deltakosh](https://github.com/deltakosh))
  - New Unity 5 Editor Toolkit. Complete pipeline integration [Doc](TODO) - ([MackeyK24](https://github.com/MackeyK24))
  - New DebugLayer. [Doc](TODO) - ([temechon](https://github.com/temechon))
  - New `VideoTexture.CreateFromWebCam` to generate video texture using WebRTC. [Demo](https://www.babylonjs-playground.com#1R77YT#2) - (Sebastien Vandenberghe)(https://github.com/sebavanmicrosoft) / ([deltakosh](https://github.com/deltakosh))
  - New `HolographicCamera` to support rendering on Windows Holographic. - ([sebavan](https://github.com/sebavan))
+ - babylon.fontTexture.ts was moved from babylon.js to canvas2D ([nockawa](https://github.com/nockawa))
 
 ### Updates
+ - Added addChild, removeChild, setParent to AbstractMesh.  ([abow](https://github.com/abow))
  - `Effect.getVertexShaderSource()` and `Effect.getFragmentShaderSource()` now returns the effective shader code (including evaluation of #define) ([deltakosh](https://github.com/deltakosh))
 
+### Canvas2D
+
+#### Major Updates
+ - Support of [Scale9Sprite](http://doc.babylonjs.com/overviews/Canvas2D_Sprite2D#scale9sprite-feature) feature in Sprite2D ([nockawa](https://github.com/nockawa))
+ - Support of [AtlasPicture](http://doc.babylonjs.com/overviews/Canvas2D_AtlasPicture) to store many pictures into a bit one, with the possibility to create one/many Sprite2D out of it. ([nockawa](https://github.com/nockawa))
+ - Support of BMFont with the BitmaptFontTexture class, Text2D has now a bitmapFontTexture setting in the constructor to display text using a BitmapFontTexture ([nockawa](https://github.com/nockawa))
+
+#### Minor Updates
+ - Fix Rotation issue when the Parent's Primitive hadn't a identity scale. ([nockawa](https://github.com/nockawa))
+ - Primitive's position computed from TrackedNode are now hidden when the node is out of the Viewing Frustum ([nockawa](https://github.com/nockawa))
+
+
 ### Exporters
     
 ### API doc

+ 7 - 1
inspector/src/tabs/StatsTab.ts

@@ -228,6 +228,12 @@ module INSPECTOR {
                 this._updatableProperties.push({ 
                     elem:elemValue, 
                     updateFct:() => { return (this._engine.getCaps().drawBuffersExtension ? "Yes" : "No")}
+                });                 
+                elemLabel = this._createStatLabel("Vertex array object", this._panel);
+                elemValue = Helpers.CreateDiv('stat-value', this._panel);
+                this._updatableProperties.push({ 
+                    elem:elemValue, 
+                    updateFct:() => { return (this._engine.getCaps().vertexArrayObject ? "Yes" : "No")}
                 }); 
             }
 
@@ -265,7 +271,7 @@ module INSPECTOR {
                 let elemValue = Helpers.CreateDiv('stat-infos', this._panel);
                 this._updatableProperties.push({ 
                     elem:elemValue, 
-                    updateFct:() => { return this._engine.webGLVersion + " - " + this._glInfo.version + " - "+this._glInfo.renderer}
+                    updateFct:() => { return "WebGL v" + this._engine.webGLVersion + " - " + this._glInfo.version + " - "+this._glInfo.renderer}
                 });
             }
 

+ 85 - 46
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -166,8 +166,17 @@ module BABYLON {
                     continue;
                 }
 
-                var inputData = animation.parameters[sampler.input];
-                var outputData = animation.parameters[sampler.output];
+                var inputData: string = null;
+                var outputData: string = null;
+
+                if (animation.parameters) {
+                    inputData = animation.parameters[sampler.input];
+                    outputData = animation.parameters[sampler.output];
+                }
+                else {
+                    inputData = sampler.input;
+                    outputData = sampler.output;
+                }
 
                 var bufferInput = GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[inputData]);
                 var bufferOutput = GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[outputData]);
@@ -176,6 +185,10 @@ module BABYLON {
                 var targetNode: any = gltfRuntime.scene.getNodeByID(targetID);
 
                 if (targetNode === null) {
+                    targetNode = gltfRuntime.scene.getNodeByName(targetID);
+                }
+
+                if (targetNode === null) {
                     Tools.Warn("Creating animation named " + anim + ". But cannot find node named " + targetID + " to attach to");
                     continue;
                 }
@@ -293,10 +306,11 @@ module BABYLON {
     */
     var configureBoneTransformation = (node: IGLTFNode): Matrix => {
         var mat: Matrix = null;
-        if (node.translation && node.rotation && node.scale) {
-            var scale = Vector3.FromArray(node.scale);
-            var rotation = Quaternion.FromArray(node.rotation);
-            var position = Vector3.FromArray(node.translation);
+
+        if (node.translation || node.rotation || node.scale) {
+            var scale = Vector3.FromArray(node.scale || [1, 1, 1]);
+            var rotation = Quaternion.FromArray(node.rotation || [0, 0, 0, 1]);
+            var position = Vector3.FromArray(node.translation || [0, 0, 0]);
 
             // Y is Up
             if (GLTFFileLoader.MakeYUP) {
@@ -318,7 +332,7 @@ module BABYLON {
     var getParentBone = (gltfRuntime: IGLTFRuntime, skins: IGLTFSkins, jointName: string, newSkeleton: Skeleton): Bone => {
         // Try to find
         for (var i = 0; i < newSkeleton.bones.length; i++) {
-            if (newSkeleton.bones[i].id === jointName) {
+            if (newSkeleton.bones[i].name === jointName) {
                 return newSkeleton.bones[i];
             }
         }
@@ -509,21 +523,10 @@ module BABYLON {
                 continue;
             }
 
-            // Check if node already exists
-            var foundBone = false;
-            for (var j = 0; j < newSkeleton.bones.length; j++) {
-                if (newSkeleton.bones[j].id === id) {
-                    foundBone = true;
-                    break;
-                }
-            }
-
-            if (foundBone) {
-                continue;
-            }
-
             // Search for parent bone
+            var foundBone = false;
             var parentBone: Bone = null;
+
             for (var j = 0; j < i; j++) {
                 var joint: IGLTFNode = getJointNode(gltfRuntime, skins.jointNames[j]).node;
 
@@ -564,17 +567,18 @@ module BABYLON {
             if (!parentBone && nodesToRoot.length === 0) {
                 var inverseBindMatrix = Matrix.FromArray(buffer, i * 16);
                 var invertMesh = Matrix.Invert(mesh.getWorldMatrix());
+
                 mat = mat.multiply(mesh.getWorldMatrix());
             }
 
-            var bone = new Bone(node.name, newSkeleton, parentBone, mat);
+            var bone = new Bone(node.jointName, newSkeleton, parentBone, mat);
             bone.id = id;
         }
 
         // Polish
         var bones = newSkeleton.bones;
         newSkeleton.bones = [];
-
+        
         for (var i = 0; i < skins.jointNames.length; i++) {
             var jointNode: IJointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
 
@@ -590,9 +594,9 @@ module BABYLON {
             }
         }
 
-        // Finish
         newSkeleton.prepare();
 
+        // Finish
         for (var i = 0; i < nodesToRootToAdd.length; i++) {
             newSkeleton.bones.push(nodesToRootToAdd[i]);
         }
@@ -834,7 +838,7 @@ module BABYLON {
                 }
 
                 if (newMesh.skeleton !== null) {
-                    newMesh.useBones = true;
+                    //newMesh.useBones = true;
                 }
 
                 lastNode = newMesh;
@@ -1001,8 +1005,10 @@ module BABYLON {
             }
         }
 
-        for (var i = 0; i < node.children.length; i++) {
-            traverseNodes(gltfRuntime, node.children[i], newNode, meshIncluded);
+        if (node.children) {
+            for (var i = 0; i < node.children.length; i++) {
+                traverseNodes(gltfRuntime, node.children[i], newNode, meshIncluded);
+            }
         }
     };
 
@@ -1013,8 +1019,19 @@ module BABYLON {
         // Nodes
         var currentScene: IGLTFScene = <IGLTFScene>gltfRuntime.currentScene;
 
-        for (var i = 0; i < currentScene.nodes.length; i++) {
-            traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+        if (currentScene) {
+            for (var i = 0; i < currentScene.nodes.length; i++) {
+                traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+            }
+        }
+        else {
+            for (var thing in gltfRuntime.scenes) {
+                currentScene = <IGLTFScene>gltfRuntime.scenes[thing];
+
+                for (var i = 0; i < currentScene.nodes.length; i++) {
+                    traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+                }
+            }
         }
 
         // Set animations
@@ -1030,6 +1047,8 @@ module BABYLON {
     * onBind shaderrs callback to set uniforms and matrices
     */
     var onBindShaderMaterial = (mesh: Mesh, gltfRuntime: IGLTFRuntime, unTreatedUniforms: Object, shaderMaterial: ShaderMaterial, technique: IGLTFTechnique, material: IGLTFMaterial, onSuccess: (shaderMaterial: ShaderMaterial) => void) => {
+        var materialValues = material.values || technique.parameters;
+
         for (var unif in unTreatedUniforms) {
             var uniform: IGLTFTechniqueParameter = unTreatedUniforms[unif];
             var type = uniform.type;
@@ -1051,15 +1070,15 @@ module BABYLON {
                 }
             }
             else {
-                var value = material.values[technique.uniforms[unif]];
+                var value = materialValues[technique.uniforms[unif]];
                 if (!value) {
                     continue;
                 }
 
                 if (type === EParameterType.SAMPLER_2D) {
-                    var texture: Texture = gltfRuntime.textures[value].babylonTexture;
+                    var texture: Texture = gltfRuntime.textures[material.values ? value : uniform.value].babylonTexture;
 
-                    if (texture === null) {
+                    if (texture === null || texture === undefined) {
                         continue;
                     }
 
@@ -1079,7 +1098,7 @@ module BABYLON {
     * Loads the appropriate textures
     */
     var prepareShaderMaterialUniforms = (gltfRuntime: IGLTFRuntime, shaderMaterial: ShaderMaterial, technique: IGLTFTechnique, material: IGLTFMaterial, unTreatedUniforms: Object) => {
-        var materialValues = material.values;
+        var materialValues = material.values || technique.parameters;
         var techniqueUniforms = technique.uniforms;
 
         /**
@@ -1089,31 +1108,33 @@ module BABYLON {
             var uniform: IGLTFTechniqueParameter = unTreatedUniforms[unif];
             var type = uniform.type;
             var value = materialValues[techniqueUniforms[unif]];
-            
+
             if (value === undefined) {
                 // In case the value is the same for all materials
-                value = <any> uniform.value;
+                value = <any>uniform.value;
             }
 
             if (!value) {
                 continue;
             }
 
-            var onLoadTexture = (texture: Texture) => {
-                if (uniform.value) {
-                    // Static uniform
-                    shaderMaterial.setTexture(unif, texture);
-                    delete unTreatedUniforms[unif];
+            var onLoadTexture = (uniformName: string) => {
+                return (texture: Texture) => {
+                    if (uniform.value) {
+                        // Static uniform
+                        shaderMaterial.setTexture(uniformName, texture);
+                        delete unTreatedUniforms[uniformName];
+                    }
                 }
             };
 
             // Texture (sampler2D)
             if (type === EParameterType.SAMPLER_2D) {
-                GLTFFileLoaderExtension.LoadTextureAsync(gltfRuntime, <string>value, onLoadTexture, () => onLoadTexture(null));
+                GLTFFileLoaderExtension.LoadTextureAsync(gltfRuntime, material.values ? value : uniform.value, onLoadTexture(unif), () => onLoadTexture(null));
             }
             // Others
             else {
-                if (uniform.value && GLTFUtils.SetUniform(shaderMaterial, unif, value, type)) {
+                if (uniform.value && GLTFUtils.SetUniform(shaderMaterial, unif, material.values ? value : uniform.value, type)) {
                     // Static uniform
                     delete unTreatedUniforms[unif];
                 }
@@ -1200,9 +1221,10 @@ module BABYLON {
                 materials: {},
                 animations: {},
                 skins: {},
-                currentScene: {},
                 extensionsUsed: [],
 
+                scenes: {},
+
                 buffersCount: 0,
                 shaderscount: 0,
 
@@ -1288,6 +1310,10 @@ module BABYLON {
                 parseObject(parsedData.skins, "skins", gltfRuntime);
             }
 
+            if (parsedData.scenes) {
+                gltfRuntime.scenes = parsedData.scenes;
+            }
+
             if (parsedData.scene && parsedData.scenes) {
                 gltfRuntime.currentScene = parsedData.scenes[parsedData.scene];
             }
@@ -1483,7 +1509,7 @@ module BABYLON {
                 attributes: attributes,
                 uniforms: uniforms,
                 samplers: samplers,
-                needAlphaBlending: states.functions && states.functions.blendEquationSeparate
+                needAlphaBlending: states && states.enable && states.enable.indexOf(3042) !== -1
             };
 
             Effect.ShadersStore[program.vertexShader + id + "VertexShader"] = newVertexShader;
@@ -1494,7 +1520,7 @@ module BABYLON {
             shaderMaterial.onCompiled = onShaderCompileSuccess(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms, onSuccess);
             shaderMaterial.sideOrientation = Material.CounterClockWiseSideOrientation;
 
-            if (states.functions) {
+            if (states && states.functions) {
                 var functions = states.functions;
                 if (functions.cullFace && functions.cullFace[0] !== ECullingType.BACK) {
                     shaderMaterial.backFaceCulling = false;
@@ -1725,8 +1751,21 @@ module BABYLON {
         private _createNodes(gltfRuntime: IGLTFRuntime): void {
             var currentScene = <IGLTFScene>gltfRuntime.currentScene;
 
-            for (var i = 0; i < currentScene.nodes.length; i++) {
-                traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+            if (currentScene) {
+                // Only one scene even if multiple scenes are defined
+                for (var i = 0; i < currentScene.nodes.length; i++) {
+                    traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+                }
+            }
+            else {
+                // Load all scenes
+                for (var thing in gltfRuntime.scenes) {
+                    currentScene = <IGLTFScene>gltfRuntime.scenes[thing];
+
+                    for (var i = 0; i < currentScene.nodes.length; i++) {
+                        traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+                    }
+                }
             }
         }
     };

+ 5 - 1
loaders/src/glTF/babylon.glTFFileLoaderInterfaces.ts

@@ -345,8 +345,12 @@ module BABYLON {
         materials: Object;
         animations: Object;
         skins: Object;
-        currentScene: Object;
+
+        currentScene?: Object;
+        scenes: Object; // v1.1
+
         extensionsUsed: string[];
+        extensionsRequired?: string[]; // v1.1
 
         buffersCount: number;
         shaderscount: number;

+ 3 - 3
src/Animations/babylon.animatable.ts

@@ -99,9 +99,9 @@
         }
 
         public stop(animationName?: string): void {
-            var index = this._scene._activeAnimatables.indexOf(this);
+            var idx = this._scene._activeAnimatables.indexOf(this);
 
-            if (index > -1) {
+            if (idx > -1) {
                 var animations = this._animations;
                 var numberOfAnimationsStopped = 0;
                 for (var index = animations.length - 1; index >= 0; index--) {
@@ -114,7 +114,7 @@
                 }
 
                 if (animations.length == numberOfAnimationsStopped) {
-                    this._scene._activeAnimatables.splice(index, 1);
+                    this._scene._activeAnimatables.splice(idx, 1);
 
                     if (this.onAnimationEnd) {
                         this.onAnimationEnd();

+ 4 - 0
src/Audio/babylon.sound.ts

@@ -227,6 +227,10 @@ module BABYLON {
             }
         }
 
+        public isReady(): boolean {
+            return this._isReadyToPlay;
+        }
+
         private _soundLoaded(audioData: ArrayBuffer) {
             this._isLoaded = true;
             Engine.audioEngine.audioContext.decodeAudioData(audioData, (buffer) => {

+ 1 - 0
src/Cameras/babylon.camera.ts

@@ -353,6 +353,7 @@
                         result.push(i);
                         continue;
                     }
+                    index = atIndices[i];
                     this._postProcesses.splice(index, 1);
                 }
             }

+ 53 - 7
src/Materials/babylon.effect.ts

@@ -63,7 +63,9 @@
         public onCompiled: (effect: Effect) => void;
         public onError: (effect: Effect, errors: string) => void;
         public onBind: (effect: Effect) => void;
+        public uniqueId = 0;
 
+        private static _uniqueIdSeed = 0;
         private _engine: Engine;
         private _uniformsNames: string[];
         private _samplers: string[];
@@ -91,6 +93,8 @@
 
             this._indexParameters = indexParameters;
 
+            this.uniqueId = Effect._uniqueIdSeed++;
+
             var vertexSource;
             var fragmentSource;
 
@@ -116,15 +120,23 @@
 
             this._loadVertexShader(vertexSource, vertexCode => {
                 this._processIncludes(vertexCode, vertexCodeWithIncludes => {
-                    this._loadFragmentShader(fragmentSource, (fragmentCode) => {
-                        this._processIncludes(fragmentCode, fragmentCodeWithIncludes => {
-                            this._prepareEffect(vertexCodeWithIncludes, fragmentCodeWithIncludes, attributesNames, defines, fallbacks);
+                    this._processShaderConversion(vertexCodeWithIncludes, false, migratedVertexCode => {
+                        this._loadFragmentShader(fragmentSource, (fragmentCode) => {
+                            this._processIncludes(fragmentCode, fragmentCodeWithIncludes => {
+                                this._processShaderConversion(fragmentCodeWithIncludes, true, migratedFragmentCode => {
+                                    this._prepareEffect(migratedVertexCode, migratedFragmentCode, attributesNames, defines, fallbacks);
+                                });
+                            });
                         });
                     });
                 });
             });
         }
 
+        public get key(): string {
+            return this._key;
+        }
+
         // Properties
         public isReady(): boolean {
             return this._isReady;
@@ -260,6 +272,44 @@
                 Tools.Error("Fragment shader:" + this.name);
             }
         }
+        private _processShaderConversion(sourceCode: string, isFragment: boolean, callback: (data: any) => void): void {
+
+            var preparedSourceCode = this._processPrecision(sourceCode);
+
+            if (this._engine.webGLVersion == 1) {
+                callback(preparedSourceCode);
+                return;
+            }
+
+            // Already converted
+            if (preparedSourceCode.indexOf("#version 3") !== -1) {
+                callback(preparedSourceCode);
+                return;
+            }
+            
+            // Remove extensions 
+            // #extension GL_OES_standard_derivatives : enable
+            // #extension GL_EXT_shader_texture_lod : enable
+            // #extension GL_EXT_frag_depth : enable
+            var regex = /#extension.+(GL_OES_standard_derivatives|GL_EXT_shader_texture_lod|GL_EXT_frag_depth).+enable/g;
+            var result = preparedSourceCode.replace(regex, "");
+
+            // Migrate to GLSL v300
+            result = result.replace(/varying\s/g, isFragment ? "in " : "out ");
+            result = result.replace(/attribute[ \t]/g, "in ");
+            result = result.replace(/[ \t]attribute/g, " in");
+            
+            if (isFragment) {
+                result = result.replace(/textureCubeLodEXT\(/g, "textureLod(");
+                result = result.replace(/texture2D\(/g, "texture(");
+                result = result.replace(/textureCube\(/g, "texture(");
+                result = result.replace(/gl_FragDepthEXT/g, "gl_FragDepth");
+                result = result.replace(/gl_FragColor/g, "glFragColor");
+                result = result.replace(/void\s+?main\(/g, "out vec4 glFragColor;\nvoid main(");
+            }
+            
+            callback(result);
+        }
 
         private _processIncludes(sourceCode: string, callback: (data: any) => void): void {
             var regex = /#include<(.+)>(\((.*)\))*(\[(.*)\])*/g;
@@ -344,10 +394,6 @@
             try {
                 var engine = this._engine;
 
-                // Precision
-                vertexSourceCode = this._processPrecision(vertexSourceCode);
-                fragmentSourceCode = this._processPrecision(fragmentSourceCode);
-
                 this._program = engine.createShaderProgram(vertexSourceCode, fragmentSourceCode, defines);
 
                 this._uniforms = engine.getUniforms(this._program, this._uniformsNames);

+ 5 - 0
src/Materials/babylon.pbrMaterial.ts

@@ -809,6 +809,11 @@
                         if (this.invertNormalMapY) {
                             this._defines.INVERTNORMALMAPY = true;
                         }
+
+                        if (scene._mirroredCameraPosition) {
+                            this._defines.INVERTNORMALMAPX = !this._defines.INVERTNORMALMAPX;
+                            this._defines.INVERTNORMALMAPY = !this._defines.INVERTNORMALMAPY;
+                        }
                     }
                 }
 

+ 5 - 0
src/Materials/babylon.standardMaterial.ts

@@ -435,6 +435,11 @@
                         if (this.invertNormalMapY) {
                             this._defines.INVERTNORMALMAPY = true;
                         }
+
+                        if (scene._mirroredCameraPosition) {
+                            this._defines.INVERTNORMALMAPX = !this._defines.INVERTNORMALMAPX;
+                            this._defines.INVERTNORMALMAPY = !this._defines.INVERTNORMALMAPY;
+                        }
                     }
                 }
 

+ 3 - 2
src/Math/babylon.math.ts

@@ -239,6 +239,7 @@
         public static Magenta(): Color3 { return new Color3(1, 0, 1); }
         public static Yellow(): Color3 { return new Color3(1, 1, 0); }
         public static Gray(): Color3 { return new Color3(0.5, 0.5, 0.5); }
+        public static Random(): Color3 { return new Color3(Math.random(), Math.random(), Math.random()); }
     }
 
     export class Color4 {
@@ -1226,7 +1227,7 @@
             world.multiplyToRef(view, matrix)
             matrix.multiplyToRef(projection, matrix);
             matrix.invert();
-            var screenSource = new Vector3(source.x / viewportWidth * 2 - 1, -(source.y / viewportHeight * 2 - 1), source.z);
+            var screenSource = new Vector3(source.x / viewportWidth * 2 - 1, -(source.y / viewportHeight * 2 - 1), 2 * source.z - 1.0);
             var vector = Vector3.TransformCoordinates(screenSource, matrix);
             var num = screenSource.x * matrix.m[3] + screenSource.y * matrix.m[7] + screenSource.z * matrix.m[11] + matrix.m[15];
 
@@ -4081,4 +4082,4 @@
             Matrix.Zero(), Matrix.Zero(),
             Matrix.Zero(), Matrix.Zero()];                      // 6 temp Matrices at once should be enough
     }
-}
+}

+ 90 - 2
src/Mesh/babylon.abstractMesh.ts

@@ -1171,10 +1171,12 @@
             }
 
             // SubMeshes
-            this.releaseSubMeshes();
+            if (this.getClassName() !== "InstancedMesh"){
+                this.releaseSubMeshes();
+            }
 
             // Engine
-            this.getScene().getEngine().unbindAllAttributes();
+            this.getScene().getEngine().wipeCaches();
 
             // Remove from scene
             this.getScene().removeMesh(this);
@@ -1275,6 +1277,92 @@
 
         }
 
+        public setParent(mesh:AbstractMesh, keepWorldPositionRotation = false): void{
+
+            var child = this;
+            var parent = mesh;
+
+            if(mesh == null){
+
+                if(child.parent && keepWorldPositionRotation){
+                  
+                    var rotation = Tmp.Quaternion[0];
+                    var position = Tmp.Vector3[0];
+                    var scale = Tmp.Vector3[1];
+
+                    child.getWorldMatrix().decompose(scale, rotation, position);
+
+                    if (child.rotationQuaternion) {
+                        child.rotationQuaternion.copyFrom(rotation);
+                    } else {
+                        rotation.toEulerAnglesToRef(child.rotation);
+                    }
+
+                    child.position.x = position.x;
+                    child.position.y = position.y;
+                    child.position.z = position.z;
+
+               }
+
+            } else {
+
+                if(keepWorldPositionRotation){
+                    
+                    var rotation = Tmp.Quaternion[0];
+                    var position = Tmp.Vector3[0];
+                    var scale = Tmp.Vector3[1];
+                    var m1 = Tmp.Matrix[0];
+                    var m2 = Tmp.Matrix[1];
+
+                    parent.getWorldMatrix().decompose(scale, rotation, position);
+
+                    rotation.toRotationMatrix(m1);
+                    m2.setTranslation(position);
+
+                    m2.multiplyToRef(m1, m1);
+
+                    var invParentMatrix = Matrix.Invert(m1);
+
+                    var m = child.getWorldMatrix().multiply(invParentMatrix);
+
+                    m.decompose(scale, rotation, position);
+
+                    if (child.rotationQuaternion) {
+                        child.rotationQuaternion.copyFrom(rotation);
+                    } else {
+                        rotation.toEulerAnglesToRef(child.rotation);
+                    }
+
+                    invParentMatrix = Matrix.Invert(parent.getWorldMatrix());
+
+                    var m = child.getWorldMatrix().multiply(invParentMatrix);
+
+                    m.decompose(scale, rotation, position);
+
+                    child.position.x = position.x;
+                    child.position.y = position.y;
+                    child.position.z = position.z;
+
+                }
+
+            }
+
+            child.parent = parent;
+
+        }
+
+        public addChild(mesh:AbstractMesh, keepWorldPositionRotation = false): void{
+
+            mesh.setParent(this, keepWorldPositionRotation);
+
+        }
+
+        public removeChild(mesh:AbstractMesh, keepWorldPositionRotation = false): void{
+
+            mesh.setParent(null, keepWorldPositionRotation);
+
+        }
+
         public getAbsolutePivotPointToRef(result:Vector3): void{
 
             result.x = this._pivotMatrix.m[12];

+ 39 - 8
src/Mesh/babylon.geometry.ts

@@ -21,6 +21,7 @@
         public _boundingInfo: BoundingInfo;
         public _delayLoadingFunction: (any: any, geometry: Geometry) => void;
         public _softwareSkinningRenderId: number;
+        private _vertexArrayObjects: { [key: string]: WebGLVertexArrayObject; };
 
         /**
          *  The Bias Vector to apply on the bounding elements (box/sphere), the max extend is computed as v += v * bias.x + bias.y, the min is computed as v -= v * bias.x + bias.y 
@@ -58,6 +59,10 @@
                 this._indices = [];
             }
 
+            if (this._engine.getCaps().vertexArrayObject) {
+                this._vertexArrayObjects = {};
+            }
+
             // applyToMesh
             if (mesh) {
                 if (mesh instanceof LinesMesh) {
@@ -136,6 +141,11 @@
             }
 
             this.notifyUpdate(kind);
+
+            if (this._vertexArrayObjects) {
+                this._disposeVertexArrayObjects();
+                this._vertexArrayObjects = {}; // Will trigger a rebuild of the VAO if supported
+            }
         }
 
         public updateVerticesDataDirectly(kind: string, data: Float32Array, offset: number): void {
@@ -191,6 +201,24 @@
             }
         }
 
+        public _bind(effect: Effect, indexToBind: WebGLBuffer = undefined): void {  
+            if (indexToBind === undefined) {
+                indexToBind = this._indexBuffer;
+            }
+
+            if (indexToBind != this._indexBuffer || !this._vertexArrayObjects) {
+                this._engine.bindBuffers(this.getVertexBuffers(), indexToBind, effect);
+                return;
+            }
+
+            // Using VAO
+            if (!this._vertexArrayObjects[effect.key]) {
+                this._vertexArrayObjects[effect.key] = this._engine.recordVertexArrayObject(this.getVertexBuffers(), indexToBind, effect);
+            }
+
+            this._engine.bindVertexArrayObject(this._vertexArrayObjects[effect.key], indexToBind);
+        }
+
         public getTotalVertices(): number {
             if (!this.isReady()) {
                 return 0;
@@ -319,14 +347,6 @@
                 return;
             }
 
-            for (var kind in this._vertexBuffers) {
-                this._vertexBuffers[kind].dispose();
-            }
-
-            if (this._indexBuffer && this._engine._releaseBuffer(this._indexBuffer)) {
-                this._indexBuffer = null;
-            }
-
             meshes.splice(index, 1);
 
             mesh._geometry = null;
@@ -489,6 +509,15 @@
             return this._isDisposed;
         }
 
+        private _disposeVertexArrayObjects(): void {
+            if (this._vertexArrayObjects) {
+                for (var kind in this._vertexArrayObjects) {
+                    this._engine.releaseVertexArrayObject(this._vertexArrayObjects[kind]);
+                }
+                this._vertexArrayObjects = {};
+            }
+        }
+
         public dispose(): void {
             var meshes = this._meshes;
             var numOfMeshes = meshes.length;
@@ -498,6 +527,8 @@
             }
             this._meshes = [];
 
+            this._disposeVertexArrayObjects();
+
             for (var kind in this._vertexBuffers) {
                 this._vertexBuffers[kind].dispose();
             }

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

@@ -153,7 +153,7 @@
             return result;
         }
 
-        // Dispoe
+        // Dispose
         public dispose(doNotRecurse?: boolean): void {
 
             // Remove from mesh

+ 22 - 2
src/Mesh/babylon.mesh.ts

@@ -121,6 +121,12 @@
         private _sourcePositions: Float32Array; // Will be used to save original positions when using software skinning
         private _sourceNormals: Float32Array; // Will be used to save original normals when using software skinning
 
+        // Will be used to save a source mesh reference, If any
+        private _source: BABYLON.Mesh = null; 
+        public get source(): BABYLON.Mesh {
+            return this._source;
+        }
+
         /**
          * @constructor
          * @param {string} name The value used by scene.getMeshByName() to do a lookup.
@@ -130,11 +136,15 @@
          * @param {boolean} doNotCloneChildren When cloning, skip cloning child meshes of source, default False.
          *                  When false, achieved by calling a clone(), also passing False.
          *                  This will make creation of children, recursive.
+         * @param {boolean} clonePhysicsImpostor When cloning, include cloning mesh physics impostor, default True.
          */
         constructor(name: string, scene: Scene, parent: Node = null, source?: Mesh, doNotCloneChildren?: boolean, clonePhysicsImpostor: boolean = true) {
             super(name, scene);
 
             if (source) {
+                // Source mesh
+                this._source = source;
+
                 // Geometry
                 if (source._geometry) {
                     source._geometry.applyToMesh(this);
@@ -825,7 +835,7 @@
             }
 
             // VBOs
-            engine.bindBuffers(this._geometry.getVertexBuffers(), indexToBind, effect);
+            this._geometry._bind(effect, indexToBind);
         }
 
         public _draw(subMesh: SubMesh, fillMode: number, instancesCount?: number): void {
@@ -976,7 +986,8 @@
             } else {
                 instancesBuffer.updateDirectly(this._instancesData, 0, instancesCount);
             }
-            engine.bindBuffers(this.geometry.getVertexBuffers(), this.geometry.getIndexBuffer(), effect);
+
+            this.geometry._bind(effect);
 
             this._draw(subMesh, fillMode, instancesCount);
 
@@ -1337,6 +1348,15 @@
                 this._geometry.releaseForMesh(this, true);
             }
 
+            // Sources
+            var meshes = this.getScene().meshes;
+            meshes.forEach((mesh: Mesh) => {
+                if (mesh._source && mesh._source === this) {
+                    mesh._source = null;
+                }
+            });
+            this._source = null;
+
             // Instances
             if (this._instancesBuffer) {
                 this._instancesBuffer.dispose();

+ 33 - 5
src/Particles/babylon.particleSystem.ts

@@ -41,6 +41,9 @@
 
         public layerMask: number = 0x0FFFFFFF;
 
+        public customShader: any = null;
+        public preventAutoStart: boolean = false;
+        
         /**
         * An event triggered when the system is disposed.
         * @type {BABYLON.Observable}
@@ -447,9 +450,17 @@
 
         // Clone
         public clone(name: string, newEmitter: any): ParticleSystem {
-            var result = new ParticleSystem(name, this._capacity, this._scene);
+            var custom: Effect = null;
+            var program: any = null;
+            if (this.customShader != null) {
+                program = this.customShader;
+                var defines: string = (program.shaderOptions.defines.length > 0) ? program.shaderOptions.defines.join("\n") : "";
+                custom = this._scene.getEngine().createEffectForParticles(program.shaderPath.fragmentElement, program.shaderOptions.uniforms, program.shaderOptions.samplers, defines);
+            }
+            var result = new ParticleSystem(name, this._capacity, this._scene, custom);
+            result.customShader = program;
 
-            Tools.DeepCopy(this, result, ["particles"]);
+            Tools.DeepCopy(this, result, ["particles", "customShader"]);
 
             if (newEmitter === undefined) {
                 newEmitter = this.emitter;
@@ -460,7 +471,9 @@
                 result.particleTexture = new Texture(this.particleTexture.url, this._scene);
             }
 
-            result.start();
+            if (!this.preventAutoStart) {
+                result.start();
+            }
 
             return result;
         }
@@ -509,18 +522,33 @@
             serializationObject.targetStopDuration = this.targetStopDuration;
             serializationObject.textureMask = this.textureMask.asArray();
             serializationObject.blendMode = this.blendMode;
+            serializationObject.customShader = this.customShader;
+            serializationObject.preventAutoStart = this.preventAutoStart;
 
             return serializationObject;
         }
 
         public static Parse(parsedParticleSystem: any, scene: Scene, rootUrl: string): ParticleSystem {
             var name = parsedParticleSystem.name;
-            var particleSystem = new ParticleSystem(name, parsedParticleSystem.capacity, scene);
+            var custom: Effect = null;
+            var program: any = null;
+            if (parsedParticleSystem.customShader) {
+                program = parsedParticleSystem.customShader;
+                var defines: string = (program.shaderOptions.defines.length > 0) ? program.shaderOptions.defines.join("\n") : "";
+                custom = scene.getEngine().createEffectForParticles(program.shaderPath.fragmentElement, program.shaderOptions.uniforms, program.shaderOptions.samplers, defines);
+            }
+            var particleSystem = new ParticleSystem(name, parsedParticleSystem.capacity, scene, custom);
+            particleSystem.customShader = program;
 
             if (parsedParticleSystem.id) {
                 particleSystem.id = parsedParticleSystem.id;
             }
 
+            // Auto start
+            if (parsedParticleSystem.preventAutoStart) {
+                particleSystem.preventAutoStart = parsedParticleSystem.preventAutoStart;
+            }
+
             // Texture
             if (parsedParticleSystem.textureName) {
                 particleSystem.particleTexture = new Texture(rootUrl + parsedParticleSystem.textureName, scene);
@@ -569,7 +597,7 @@
             particleSystem.textureMask = Color4.FromArray(parsedParticleSystem.textureMask);
             particleSystem.blendMode = parsedParticleSystem.blendMode;
 
-            if (!parsedParticleSystem.preventAutoStart) {
+            if (!particleSystem.preventAutoStart) {
                 particleSystem.start();
             }
 

+ 1 - 25
src/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -43,7 +43,7 @@
             var worldPoint = new CANNON.Vec3(contactPoint.x, contactPoint.y, contactPoint.z);
             var impulse = new CANNON.Vec3(force.x, force.y, force.z);
 
-            impostor.physicsBody.applyImpulse(impulse, worldPoint);
+            impostor.physicsBody.applyForce(impulse, worldPoint);
         }
 
         public generatePhysicsBody(impostor: PhysicsImpostor) {
@@ -153,21 +153,6 @@
                 maxForce: jointData.nativeParams.maxForce,
                 collideConnected: !!jointData.collision
             };
-            //Not needed, Cannon has a collideConnected flag
-            /*if (!jointData.collision) {
-                //add 1st body to a collision group of its own, if it is not in 1
-                if (mainBody.collisionFilterGroup === 1) {
-                    mainBody.collisionFilterGroup = this._currentCollisionGroup;
-                    this._currentCollisionGroup <<= 1;
-                }
-                if (connectedBody.collisionFilterGroup === 1) {
-                    connectedBody.collisionFilterGroup = this._currentCollisionGroup;
-                    this._currentCollisionGroup <<= 1;
-                }
-                //add their mask to the collisionFilterMask of each other:
-                connectedBody.collisionFilterMask = connectedBody.collisionFilterMask | ~mainBody.collisionFilterGroup;
-                mainBody.collisionFilterMask = mainBody.collisionFilterMask | ~connectedBody.collisionFilterGroup;
-            }*/
             switch (impostorJoint.joint.type) {
                 case PhysicsJoint.HingeJoint:
                 case PhysicsJoint.Hinge2Joint:
@@ -477,15 +462,6 @@
                 if (maxForce) {
                     this.setLimit(joint, maxForce);
                 }
-                //a hack for force application
-                /*var torque = new CANNON.Vec3();
-                var axis = joint.physicsJoint.axisB;
-                var body = joint.physicsJoint.bodyB;
-                var bodyTorque = body.torque;
-
-                axis.scale(force, torque);
-                body.vectorToWorldFrame(torque, torque);
-                bodyTorque.vadd(torque, bodyTorque);*/
             }
         }
 

+ 2 - 2
src/Physics/Plugins/babylon.oimoJSPlugin.ts

@@ -1,7 +1,7 @@
 module BABYLON {
     declare var OIMO;
 
-    export class OimoJSPlugin {
+    export class OimoJSPlugin implements IPhysicsEnginePlugin {
 
         public world: any;
         public name: string = "OimoJSPlugin";
@@ -365,7 +365,7 @@ module BABYLON {
             impostor.physicsBody.awake();
         }
 
-        public updateDistanceJoint(joint: IMotorEnabledJoint, maxDistance: number, minDistance?: number) {
+        public updateDistanceJoint(joint: PhysicsJoint, maxDistance: number, minDistance?: number) {
             joint.physicsJoint.limitMotor.upperLimit = maxDistance;
             if (minDistance !== void 0) {
                 joint.physicsJoint.limitMotor.lowerLimit = minDistance;

+ 1 - 1
src/Physics/babylon.physicsEngine.ts

@@ -195,7 +195,7 @@
         sleepBody(impostor: PhysicsImpostor);
         wakeUpBody(impostor: PhysicsImpostor);
         //Joint Update
-        updateDistanceJoint(joint: DistanceJoint, maxDistance:number, minDistance?: number);
+        updateDistanceJoint(joint: PhysicsJoint, maxDistance:number, minDistance?: number);
         setMotor(joint: IMotorEnabledJoint, speed: number, maxForce?: number, motorIndex?: number);
         setLimit(joint: IMotorEnabledJoint, upperLimit: number, lowerLimit?: number, motorIndex?: number);
         dispose();

+ 10 - 7
src/Physics/babylon.physicsImpostor.ts

@@ -212,9 +212,6 @@ module BABYLON {
             return this._physicsEngine.getPhysicsPlugin().getLinearVelocity(this);
         }
 
-        /**
-         * Set the body's linear velocity.
-         */
         public setLinearVelocity(velocity: Vector3) {
             this._physicsEngine.getPhysicsPlugin().setLinearVelocity(this, velocity);
         }
@@ -223,9 +220,6 @@ module BABYLON {
             return this._physicsEngine.getPhysicsPlugin().getAngularVelocity(this);
         }
 
-        /**
-         * Set the body's linear velocity.
-         */
         public setAngularVelocity(velocity: Vector3) {
             this._physicsEngine.getPhysicsPlugin().setAngularVelocity(this, velocity);
         }
@@ -330,11 +324,20 @@ module BABYLON {
             }
         }
 
+        /**
+         * Legacy collision detection event support
+         */
+        public onCollideEvent: (collider:BABYLON.PhysicsImpostor, collidedWith:BABYLON.PhysicsImpostor) => void = null;
+
         //event and body object due to cannon's event-based architecture.
         public onCollide = (e: { body: any }) => {
-            if (!this._onPhysicsCollideCallbacks.length) return;
+            if (!this._onPhysicsCollideCallbacks.length && !this.onCollideEvent) return;
             var otherImpostor = this._physicsEngine.getImpostorWithPhysicsBody(e.body);
             if (otherImpostor) {
+                // Legacy collision detection event support
+                if (this.onCollideEvent) {
+                    this.onCollideEvent(this, otherImpostor);
+                }
                 this._onPhysicsCollideCallbacks.filter((obj) => {
                     return obj.otherImpostors.indexOf(otherImpostor) !== -1
                 }).forEach((obj) => {

+ 3 - 3
src/Shaders/volumetricLightScattering.fragment.fx

@@ -20,9 +20,9 @@ void main(void) {
 
     for(int i=0; i < NUM_SAMPLES; i++) {
         tc -= deltaTexCoord;
-		vec4 sample = texture2D(lightScatteringSampler, tc) * 0.4;
-        sample *= illuminationDecay * weight;
-        color += sample;
+		vec4 dataSample = texture2D(lightScatteringSampler, tc) * 0.4;
+        dataSample *= illuminationDecay * weight;
+        color += dataSample;
         illuminationDecay *= decay;
     }
 

+ 142 - 0
src/Tools/babylon.khronosTextureContainer.ts

@@ -0,0 +1,142 @@
+module BABYLON.Internals {
+    /**
+     * for description see https://www.khronos.org/opengles/sdk/tools/KTX/
+     * for file layout see https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
+     */
+    export class KhronosTextureContainer {
+        static HEADER_LEN = 12 + (13 * 4); // identifier + header elements (not including key value meta-data pairs)
+        
+        // load types
+        static COMPRESSED_2D = 0; // uses a gl.compressedTexImage2D()
+        static COMPRESSED_3D = 1; // uses a gl.compressedTexImage3D()
+        static TEX_2D        = 2; // uses a gl.texImage2D()
+        static TEX_3D        = 3; // uses a gl.texImage3D()
+        
+        // elements of the header 
+        public glType : number;
+        public glTypeSize : number;
+        public glFormat : number;
+        public glInternalFormat : number;
+        public glBaseInternalFormat : number;
+        public pixelWidth : number;
+        public pixelHeight : number;
+        public pixelDepth : number;
+        public numberOfArrayElements : number;
+        public numberOfFaces : number;
+        public numberOfMipmapLevels : number;
+        public bytesOfKeyValueData : number;
+        
+        public loadType : number;
+        /**
+         * @param {ArrayBuffer} arrayBuffer- contents of the KTX container file
+         * @param {number} facesExpected- should be either 1 or 6, based whether a cube texture or or
+         * @param {boolean} threeDExpected- provision for indicating that data should be a 3D texture, not implemented
+         * @param {boolean} textureArrayExpected- provision for indicating that data should be a texture array, not implemented
+         */
+        public constructor (public arrayBuffer : any, facesExpected : number, threeDExpected? : boolean, textureArrayExpected? : boolean) {
+            // Test that it is a ktx formatted file, based on the first 12 bytes, character representation is:
+            // '«', 'K', 'T', 'X', ' ', '1', '1', '»', '\r', '\n', '\x1A', '\n'
+            // 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
+            var identifier = new Uint8Array(this.arrayBuffer, 0, 12);
+            if (identifier[ 0] !== 0xAB || identifier[ 1] !== 0x4B || identifier[ 2] !== 0x54 || identifier[ 3] !== 0x58 || identifier[ 4] !== 0x20 || identifier[ 5] !== 0x31 || 
+                identifier[ 6] !== 0x31 || identifier[ 7] !== 0xBB || identifier[ 8] !== 0x0D || identifier[ 9] !== 0x0A || identifier[10] !== 0x1A || identifier[11] !== 0x0A) {
+                Tools.Error("texture missing KTX identifier");
+                return;
+            }
+            
+            // load the reset of the header in native 32 bit int
+            var header = new Int32Array(this.arrayBuffer, 12, 13);
+            
+            // determine of the remaining header values are recorded in the opposite endianness & require conversion
+            var oppositeEndianess = header[0] === 0x01020304;
+            
+            // read all the header elements in order they exist in the file, without modification (sans endainness)
+            this.glType                = oppositeEndianess ? this.switchEndainness(header[ 1]) : header[ 1]; // must be 0 for compressed textures
+            this.glTypeSize            = oppositeEndianess ? this.switchEndainness(header[ 2]) : header[ 2]; // must be 1 for compressed textures
+            this.glFormat              = oppositeEndianess ? this.switchEndainness(header[ 3]) : header[ 3]; // must be 0 for compressed textures
+            this.glInternalFormat      = oppositeEndianess ? this.switchEndainness(header[ 4]) : header[ 4]; // the value of arg passed to gl.compressedTexImage2D(,,x,,,,)
+            this.glBaseInternalFormat  = oppositeEndianess ? this.switchEndainness(header[ 5]) : header[ 5]; // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only)
+            this.pixelWidth            = oppositeEndianess ? this.switchEndainness(header[ 6]) : header[ 6]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,)
+            this.pixelHeight           = oppositeEndianess ? this.switchEndainness(header[ 7]) : header[ 7]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,)
+            this.pixelDepth            = oppositeEndianess ? this.switchEndainness(header[ 8]) : header[ 8]; // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,)
+            this.numberOfArrayElements = oppositeEndianess ? this.switchEndainness(header[ 9]) : header[ 9]; // used for texture arrays
+            this.numberOfFaces         = oppositeEndianess ? this.switchEndainness(header[10]) : header[10]; // used for cubemap textures, should either be 1 or 6
+            this.numberOfMipmapLevels  = oppositeEndianess ? this.switchEndainness(header[11]) : header[11]; // number of levels; disregard possibility of 0 for compressed textures
+            this.bytesOfKeyValueData   = oppositeEndianess ? this.switchEndainness(header[12]) : header[12]; // the amount of space after the header for meta-data
+            
+            // Make sure we have a compressed type.  Not only reduces work, but probably better to let dev know they are not compressing.
+            if (this.glType !== 0) {
+                Tools.Error("only compressed formats currently supported");
+                return;
+            } else {
+                // value of zero is an indication to generate mipmaps @ runtime.  Not usually allowed for compressed, so disregard.
+                this.numberOfMipmapLevels = Math.max(1, this.numberOfMipmapLevels);
+            }
+            
+            if (this.pixelHeight === 0 || this.pixelDepth !== 0) {
+                Tools.Error("only 2D textures currently supported");
+                return;
+            }
+            
+            if (this.numberOfArrayElements !== 0) {
+                Tools.Error("texture arrays not currently supported");
+                return;
+            }
+            
+            if (this.numberOfFaces !== facesExpected) {
+                Tools.Error("number of faces expected" + facesExpected + ", but found " + this.numberOfFaces);
+                return;
+            }
+              
+            // we now have a completely validated file, so could use existence of loadType as success
+            // would need to make this more elaborate & adjust checks above to support more than one load type
+            this.loadType = KhronosTextureContainer.COMPRESSED_2D;
+        }
+        
+        // not as fast hardware based, but will probably never need to use
+        public switchEndainness(val : number) : number {
+            return ((val & 0xFF) << 24)
+                 | ((val & 0xFF00) << 8)
+                 | ((val >> 8) & 0xFF00)
+                 | ((val >> 24) & 0xFF);            
+        }
+        
+        /**
+         * It is assumed that the texture has already been created & is currently bound
+         */
+        public uploadLevels(gl: WebGLRenderingContext, loadMipmaps: boolean) : void {
+            switch (this.loadType){
+                case KhronosTextureContainer.COMPRESSED_2D:
+                    this._upload2DCompressedLevels(gl, loadMipmaps);
+                    break;
+                    
+                case KhronosTextureContainer.TEX_2D:
+                case KhronosTextureContainer.COMPRESSED_3D:
+                case KhronosTextureContainer.TEX_3D:
+            }
+        }
+        
+        private _upload2DCompressedLevels(gl: WebGLRenderingContext, loadMipmaps: boolean): void {
+            // initialize width & height for level 1
+            var dataOffset = KhronosTextureContainer.HEADER_LEN + this.bytesOfKeyValueData;
+            var width = this.pixelWidth;
+            var height = this.pixelHeight;
+            
+            var mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1;
+            for (var level = 0; level < mipmapCount; level++) {
+                var imageSize = new Int32Array(this.arrayBuffer, dataOffset, 1)[0]; // size per face, since not supporting array cubemaps
+                
+                for (var face = 0; face < this.numberOfFaces; face++) {
+                    var sampler = this.numberOfFaces === 1 ? gl.TEXTURE_2D : (gl.TEXTURE_CUBE_MAP_POSITIVE_X + face);
+                    var byteArray = new Uint8Array(this.arrayBuffer, dataOffset + 4, imageSize);
+                    gl.compressedTexImage2D(sampler, level, this.glInternalFormat, width, height, 0, byteArray);
+
+                    dataOffset += imageSize + 4; // size of the image + 4 for the imageSize field
+                    dataOffset += 3 - ((imageSize + 3) % 4); // add padding for odd sized image
+                }
+                width = Math.max(1.0, width * 0.5);
+                height = Math.max(1.0, height * 0.5);
+            }
+        }
+    }
+} 

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 407 - 297
src/babylon.engine.ts


+ 14 - 0
src/babylon.mixins.ts

@@ -27,6 +27,20 @@ interface Window {
     msURL: any;
 }
 
+interface WebGLVertexArrayObject {
+
+}
+
+interface WebGLRenderingContext {
+    drawArraysInstanced(mode: number, first: number, count: number, primcount: number): void;
+    drawElementsInstanced(mode: number, count: number, type: number, offset: number, primcount: number): void;
+    vertexAttribDivisor(index: number, divisor: number): void;
+
+    createVertexArray(): any;
+    bindVertexArray(vao: WebGLVertexArrayObject): void;
+    deleteVertexArray(vao: WebGLVertexArrayObject): void;
+}
+
 interface AudioContext extends EventTarget {
     decodeAudioData(audioData: ArrayBuffer, successCallback: DecodeSuccessCallback, errorCallback?: any): void;
 }

+ 17 - 17
tests/Canvas2d/Jasmine/chutzpah.json

@@ -83,7 +83,6 @@
         { "Path": "../../../src/Materials/textures/babylon.refractionTexture.js" },
         { "Path": "../../../src/Materials/textures/babylon.dynamicTexture.js" },
         { "Path": "../../../src/Materials/textures/babylon.videoTexture.js" },
-        { "Path": "../../../src/Materials/textures/babylon.fontTexture.js" },
         { "Path": "../../../src/Materials/textures/babylon.mapTexture.js" },
         { "Path": "../../../src/Materials/babylon.effect.js" },
         { "Path": "../../../src/Materials/babylon.materialHelper.js" },
@@ -92,22 +91,23 @@
         { "Path": "../../../src/Materials/babylon.standardMaterial.js" },
         { "Path": "../../../src/Materials/babylon.pbrMaterial.js" },
         { "Path": "../../../src/Materials/babylon.multiMaterial.js" },
-        { "Path": "../../../src/Canvas2d/babylon.bounding2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.canvas2dLayoutEngine.js" },
-        { "Path": "../../../src/Canvas2d/babylon.brushes2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.smartPropertyPrim.js" },
-        { "Path": "../../../src/Canvas2d/babylon.prim2dBase.js" },
-        { "Path": "../../../src/Canvas2d/babylon.modelRenderCache.js" },
-        { "Path": "../../../src/Canvas2d/babylon.renderablePrim2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.shape2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.group2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.rectangle2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.sprite2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.text2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.canvas2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.ellipse2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.lines2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.worldspacecanvas2dNode.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.fontTexture.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.bounding2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.canvas2dLayoutEngine.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.brushes2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.smartPropertyPrim.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.prim2dBase.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.modelRenderCache.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.renderablePrim2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.shape2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.group2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.rectangle2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.sprite2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.text2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.canvas2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.ellipse2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.lines2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.worldspacecanvas2dNode.js" },
         { "Path": "../../../src/GUI/babylon.gui.UIElement.js" },
         { "Path": "../../../src/GUI/babylon.gui.control.js" },
         { "Path": "../../../src/GUI/babylon.gui.label.js" },

+ 17 - 17
tests/Tools/Jasmine/chutzpah.json

@@ -83,7 +83,6 @@
         { "Path": "../../../src/Materials/textures/babylon.refractionTexture.js" },
         { "Path": "../../../src/Materials/textures/babylon.dynamicTexture.js" },
         { "Path": "../../../src/Materials/textures/babylon.videoTexture.js" },
-        { "Path": "../../../src/Materials/textures/babylon.fontTexture.js" },
         { "Path": "../../../src/Materials/textures/babylon.mapTexture.js" },
         { "Path": "../../../src/Materials/babylon.effect.js" },
         { "Path": "../../../src/Materials/babylon.materialHelper.js" },
@@ -92,22 +91,23 @@
         { "Path": "../../../src/Materials/babylon.standardMaterial.js" },
         { "Path": "../../../src/Materials/babylon.pbrMaterial.js" },
         { "Path": "../../../src/Materials/babylon.multiMaterial.js" },
-        { "Path": "../../../src/Canvas2d/babylon.bounding2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.canvas2dLayoutEngine.js" },
-        { "Path": "../../../src/Canvas2d/babylon.brushes2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.smartPropertyPrim.js" },
-        { "Path": "../../../src/Canvas2d/babylon.prim2dBase.js" },
-        { "Path": "../../../src/Canvas2d/babylon.modelRenderCache.js" },
-        { "Path": "../../../src/Canvas2d/babylon.renderablePrim2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.shape2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.group2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.rectangle2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.sprite2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.text2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.canvas2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.ellipse2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.lines2d.js" },
-        { "Path": "../../../src/Canvas2d/babylon.worldspacecanvas2dNode.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.fontTexture.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.bounding2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.canvas2dLayoutEngine.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.brushes2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.smartPropertyPrim.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.prim2dBase.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.modelRenderCache.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.renderablePrim2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.shape2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.group2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.rectangle2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.sprite2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.text2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.canvas2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.ellipse2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.lines2d.js" },
+        { "Path": "../../../canvas2d/src/Engine/babylon.worldspacecanvas2dNode.js" },
         { "Path": "../../../src/GUI/babylon.gui.UIElement.js" },
         { "Path": "../../../src/GUI/babylon.gui.control.js" },
         { "Path": "../../../src/GUI/babylon.gui.label.js" },