瀏覽代碼

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

Temechon 8 年之前
父節點
當前提交
09d569cbf8
共有 100 個文件被更改,包括 59561 次插入32225 次删除
  1. 132 0
      Exporters/3ds Max/ActionsBuilder/ActionsBuilder.csproj
  2. 0 42
      Exporters/3ds Max/ActionsBuilder/README.md
  3. 86 86
      Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.actionNode.js
  4. 118 118
      Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.contextMenu.js
  5. 351 351
      Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.js
  6. 255 255
      Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.list.js
  7. 107 101
      Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.main.js
  8. 111 110
      Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.max.js
  9. 561 550
      Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.parameters.js
  10. 85 85
      Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.toolbar.js
  11. 433 433
      Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.utils.js
  12. 631 647
      Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.viewer.js
  13. 47131 24102
      Exporters/3ds Max/ActionsBuilder/Sources/babylon.max.js
  14. 0 48
      Exporters/3ds Max/ActionsBuilder/Sources/fonts/SinkinSans/SinkinSans_NOTICE.txt
  15. 97 94
      Exporters/3ds Max/ActionsBuilder/Sources/index-debug.html
  16. 191 191
      Exporters/3ds Max/ActionsBuilder/Sources/index.css
  17. 72 72
      Exporters/3ds Max/ActionsBuilder/Sources/index.html
  18. 62 0
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.actionNode.js
  19. 100 100
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.actionNode.ts
  20. 104 0
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.contextMenu.js
  21. 148 148
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.contextMenu.ts
  22. 316 0
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.js
  23. 209 0
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.list.js
  24. 305 305
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.list.ts
  25. 96 0
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.main.js
  26. 115 106
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.main.ts
  27. 440 0
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.parameters.js
  28. 649 637
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.parameters.ts
  29. 80 0
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.toolbar.js
  30. 93 93
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.toolbar.ts
  31. 326 326
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.ts
  32. 370 0
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.utils.js
  33. 526 526
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.utils.ts
  34. 539 0
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.viewer.js
  35. 772 772
      Exporters/3ds Max/ActionsBuilder/actionsbuilder.viewer.ts
  36. 42 42
      Exporters/3ds Max/ActionsBuilder/gulpfile.js
  37. 10 11
      Exporters/3ds Max/ActionsBuilder/package.json
  38. 69 69
      Exporters/3ds Max/ActionsBuilder/raphaeljs.d.ts
  39. 31 0
      Exporters/3ds Max/ActionsBuilder/web.Debug.config
  40. 32 0
      Exporters/3ds Max/ActionsBuilder/web.Release.config
  41. 11 0
      Exporters/3ds Max/ActionsBuilder/web.config
  42. 3 0
      Exporters/3ds Max/BabylonExport.Entities/BabylonAbstractMesh.cs
  43. 16 0
      Exporters/3ds Max/BabylonExport.Entities/BabylonDirectionalLight.cs
  44. 17 0
      Exporters/3ds Max/BabylonExport.Entities/BabylonExport.Entities.csproj
  45. 0 3
      Exporters/3ds Max/BabylonExport.Entities/BabylonMesh.cs
  46. 9 0
      Exporters/3ds Max/BabylonExport.Entities/BabylonPBRMaterial.cs
  47. 11 0
      Exporters/3ds Max/BabylonExport.Entities/BabylonShadowGenerator.cs
  48. 3 3
      Exporters/3ds Max/BabylonExport.Entities/packages.config
  49. 66 0
      Exporters/3ds Max/BabylonFileConverter/BabylonFileConverter.csproj
  50. 374 0
      Exporters/3ds Max/BabylonFileConverter/BinaryConverter.cs
  51. 36 0
      Exporters/3ds Max/BabylonFileConverter/Properties/AssemblyInfo.cs
  52. 4 0
      Exporters/3ds Max/BabylonFileConverter/packages.config
  53. 二進制
      Exporters/3ds Max/Max2Babylon-0.5.0.zip
  54. 223 34
      Exporters/3ds Max/Max2Babylon.sln
  55. 273 293
      Exporters/3ds Max/Max2Babylon/2015/Max2Babylon2015.csproj
  56. 36 36
      Exporters/3ds Max/Max2Babylon/2015/Properties/AssemblyInfo.cs
  57. 63 63
      Exporters/3ds Max/Max2Babylon/2015/Properties/Resources.Designer.cs
  58. 119 119
      Exporters/3ds Max/Max2Babylon/2015/Properties/Resources.resx
  59. 6 0
      Exporters/3ds Max/Max2Babylon/2015/packages.config
  60. 9 12
      Exporters/3ds Max/Max2Babylon/2017/Max2Babylon2017.csproj
  61. 6 0
      Exporters/3ds Max/Max2Babylon/2017/packages.config
  62. 0 80
      Exporters/3ds Max/Max2Babylon/BabylonActionsBuilderActionItem.cs
  63. 95 95
      Exporters/3ds Max/Max2Babylon/Exporter/ActionBuilder/BabylonActionsBuilderActionItem.cs
  64. 27 27
      Exporters/3ds Max/Max2Babylon/Exporter/ActionBuilder/BabylonExporter.Action.cs
  65. 5 0
      Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Mesh.cs
  66. 208 187
      Exporters/3ds Max/Max2Babylon/Max2Babylon.csproj
  67. 36 36
      Exporters/3ds Max/Max2Babylon/Properties/AssemblyInfo.cs
  68. 63 63
      Exporters/3ds Max/Max2Babylon/Properties/Resources.Designer.cs
  69. 119 119
      Exporters/3ds Max/Max2Babylon/Properties/Resources.resx
  70. 二進制
      Exporters/3ds Max/Max2Babylon/Refs/BabylonFileConverter.dll
  71. 二進制
      Exporters/3ds Max/Max2Babylon/Refs/Newtonsoft.Json.dll
  72. 二進制
      Exporters/3ds Max/Max2Babylon/Refs/SharpDX.dll
  73. 1 0
      Exporters/3ds Max/Max2Babylon/Tools/WebServer.cs
  74. 5 3
      Exporters/3ds Max/Max2Babylon/packages.config
  75. 二進制
      Exporters/3ds Max/Refs/Autodesk.Max.dll
  76. 8 0
      Exporters/Maya/Tools/babylonNameTool.mel
  77. 49 0
      Exporters/Maya/Tools/babylonReskinTool.mel
  78. 36 0
      Exporters/Maya/Tools/readme.md
  79. 7 1
      Tools/Gulp/config.json
  80. 3 3
      Tools/Gulp/package.json
  81. 28 36
      canvas2D/src/Engine/babylon.atlasPicture.ts
  82. 7 0
      canvas2D/src/Engine/babylon.bounding2d.ts
  83. 90 42
      canvas2D/src/Engine/babylon.canvas2d.ts
  84. 98 31
      canvas2D/src/Engine/babylon.canvas2dLayoutEngine.ts
  85. 1 16
      canvas2D/src/Engine/babylon.ellipse2d.ts
  86. 140 33
      canvas2D/src/Engine/babylon.fontTexture.ts
  87. 6 48
      canvas2D/src/Engine/babylon.group2d.ts
  88. 1 1
      canvas2D/src/Engine/babylon.lines2d.ts
  89. 689 286
      canvas2D/src/Engine/babylon.prim2dBase.ts
  90. 7 22
      canvas2D/src/Engine/babylon.rectangle2d.ts
  91. 14 20
      canvas2D/src/Engine/babylon.renderablePrim2d.ts
  92. 6 1
      canvas2D/src/Engine/babylon.smartPropertyPrim.ts
  93. 6 23
      canvas2D/src/Engine/babylon.sprite2d.ts
  94. 75 21
      canvas2D/src/Engine/babylon.text2d.ts
  95. 1 20
      canvas2D/src/Engine/babylon.wireFrame2d.ts
  96. 582 0
      canvas2D/src/Tools/babylon.math2D.ts
  97. 7 0
      canvas2D/src/shaders/text2d.fragment.fx
  98. 33 0
      contributing.md
  99. 28 28
      dist/preview release/babylon.core.js
  100. 0 0
      dist/preview release/babylon.d.ts

+ 132 - 0
Exporters/3ds Max/ActionsBuilder/ActionsBuilder.csproj

@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.Default.props" Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.Default.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <ProjectGuid>{293A754C-3D80-42FB-99D8-7C9386CD297E}</ProjectGuid>
+    <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+    <OutputType>Library</OutputType>
+    <OutputPath>bin</OutputPath>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <DebugType>full</DebugType>
+    <DebugSymbols>true</DebugSymbols>
+    <TypeScriptToolsVersion>2.1</TypeScriptToolsVersion>
+    <UseIISExpress>true</UseIISExpress>
+    <IISExpressSSLPort />
+    <IISExpressAnonymousAuthentication />
+    <IISExpressWindowsAuthentication />
+    <IISExpressUseClassicPipelineMode />
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+    <UseGlobalApplicationHostFile />
+  </PropertyGroup>
+  <ItemGroup>
+    <Content Include="gulpfile.js" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-300Light.svg" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-300LightItalic.svg" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-500Medium.svg" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-600SemiBold.svg" />
+    <Content Include="Sources\index-debug.html" />
+    <Content Include="Sources\index.css" />
+    <Content Include="Sources\fonts.css" />
+    <Content Include="Sources\index.html" />
+    <Content Include="Sources\raphael.js" />
+    <Content Include="web.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <TypeScriptCompile Include="..\..\..\dist\preview release\babylon.d.ts">
+      <Link>babylon.d.ts</Link>
+    </TypeScriptCompile>
+    <TypeScriptCompile Include="actionsbuilder.actionNode.ts" />
+    <TypeScriptCompile Include="actionsbuilder.contextMenu.ts" />
+    <TypeScriptCompile Include="actionsbuilder.list.ts" />
+    <TypeScriptCompile Include="actionsbuilder.main.ts" />
+    <TypeScriptCompile Include="actionsbuilder.parameters.ts" />
+    <TypeScriptCompile Include="actionsbuilder.toolbar.ts" />
+    <TypeScriptCompile Include="actionsbuilder.ts" />
+    <TypeScriptCompile Include="actionsbuilder.utils.ts" />
+    <TypeScriptCompile Include="actionsbuilder.viewer.ts" />
+    <TypeScriptCompile Include="raphaeljs.d.ts" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="package.json" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-300Light.eot" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-300Light.otf" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-300Light.ttf" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-300Light.woff" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-300LightItalic.eot" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-300LightItalic.otf" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-300LightItalic.ttf" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-300LightItalic.woff" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-500Medium.eot" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-500Medium.otf" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-500Medium.ttf" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-500Medium.woff" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-600SemiBold.eot" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-600SemiBold.otf" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-600SemiBold.ttf" />
+    <Content Include="Sources\fonts\SinkinSans\SinkinSans-600SemiBold.woff" />
+    <None Include="web.Debug.config">
+      <DependentUpon>web.config</DependentUpon>
+    </None>
+    <None Include="web.Release.config">
+      <DependentUpon>web.config</DependentUpon>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Properties\" />
+  </ItemGroup>
+  <PropertyGroup>
+    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">12.0</VisualStudioVersion>
+  </PropertyGroup>
+  <PropertyGroup>
+    <RootNamespace>ActionsBuilder</RootNamespace>
+  </PropertyGroup>
+  <PropertyGroup>
+    <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
+  </PropertyGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\WebApplications\Microsoft.WebApplication.targets" Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\WebApplications\Microsoft.WebApplication.targets')" />
+  <ProjectExtensions>
+    <VisualStudio>
+      <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
+        <WebProjectProperties>
+          <UseIIS>False</UseIIS>
+          <AutoAssignPort>True</AutoAssignPort>
+          <DevelopmentServerPort>51472</DevelopmentServerPort>
+          <DevelopmentServerVPath>/</DevelopmentServerVPath>
+          <IISUrl>http://localhost:51472/</IISUrl>
+          <NTLMAuthentication>False</NTLMAuthentication>
+          <UseCustomServer>False</UseCustomServer>
+          <CustomServerUrl>
+          </CustomServerUrl>
+          <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
+        </WebProjectProperties>
+      </FlavorProperties>
+    </VisualStudio>
+  </ProjectExtensions>
+  <PropertyGroup Condition="'$(Configuration)' == 'Debug'">
+    <TypeScriptRemoveComments>false</TypeScriptRemoveComments>
+    <TypeScriptSourceMap>true</TypeScriptSourceMap>
+    <TypeScriptCompileOnSaveEnabled>True</TypeScriptCompileOnSaveEnabled>
+    <OutputPath>..\..\..\..\..\..\..\Program Files\Autodesk\3ds Max 2013\bin\assemblies\BabylonActionsBuilder\</OutputPath>
+    <TypeScriptOutDir>Sources\</TypeScriptOutDir>
+    <TypeScriptGeneratesDeclarations>False</TypeScriptGeneratesDeclarations>
+    <TypeScriptTarget>ES5</TypeScriptTarget>
+    <TypeScriptSourceRoot>$(SolutionDir)ActionsBuilder\</TypeScriptSourceRoot>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)' == 'Release'">
+    <TypeScriptRemoveComments>true</TypeScriptRemoveComments>
+    <TypeScriptSourceMap>false</TypeScriptSourceMap>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets" Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets')" />
+  <PropertyGroup>
+    <PostBuildEvent>copy "$(SolutionDir)..\..\dist\preview release\babylon.max.js" "$(SolutionDir)ActionsBuilder\Sources\babylon.max.js"
+if $(ConfigurationName) == Release gulp</PostBuildEvent>
+  </PropertyGroup>
+</Project>

+ 0 - 42
Exporters/3ds Max/ActionsBuilder/README.md

@@ -1,42 +0,0 @@
-Babylon.js Actions Builder
-==========
-
-The Actions Builder is a part of the 3ds Max plugin ([Max2Babylon](https://github.com/BabylonJS/Babylon.js/tree/master/Exporters/3ds%20Max))
-that allows to build actions without any line of code.
-
-Tutorial and informations about the Actions Builder [here](https://medium.com/babylon-js/actions-builder-b05e72aa541a)
-
-Built files are located in "./Sources"
-
-# Install and Build files
-
-### Install dependencies:
-```
-npm install
-```
-
-### Build Actions Builder:
-```
-gulp
-```
-
-### Build JS files from their respective TS files:
-```
-gulp debug
-```
-
-### Build on save:
-```
-gulp watch
-```
-
-### Update gulpfile.js to add your own files:
-```
-var files = [
-    // Files
-    ...
-    "file1.js",
-    "file2.js",
-    ...
-];
-```

+ 86 - 86
Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.actionNode.js

@@ -1,87 +1,87 @@
-var ActionsBuilder;
-(function (ActionsBuilder) {
-    var Node = (function () {
-        function Node() {
-            this.rect = null;
-            this.text = null;
-            this.line = null;
-            this.detached = false;
-            this.minimized = false;
-        }
-        /**
-        * Returns if the point (x, y) is inside the text or rect
-        * @param x: the x position of the point
-        * @param y: the y position of the point
-        */
-        Node.prototype.isPointInside = function (x, y) {
-            return this.rect.isPointInside(x, y) || this.text.isPointInside(x, y);
-        };
-        return Node;
-    })();
-    ActionsBuilder.Node = Node;
-    var Action = (function () {
-        /**
-        * Constructor
-        * @param node: The associated node to draw in the viewer
-        */
-        function Action(node) {
-            this.parent = null;
-            this.children = new Array();
-            this.name = "";
-            this.type = ActionsBuilder.Type.OBJECT;
-            this.properties = new Array();
-            this.propertiesResults = new Array();
-            this.combineArray = null;
-            this.hub = null;
-            this.combineAction = null;
-            this.node = node;
-        }
-        /*
-        * Removes a combined action from the combine array
-        * @param action: the action to remove
-        */
-        Action.prototype.removeCombinedAction = function (action) {
-            if (action === null || this.combineArray === null) {
-                return false;
-            }
-            var index = this.combineArray.indexOf(action);
-            if (index !== -1) {
-                this.combineArray.splice(index, 1);
-            }
-            return false;
-        };
-        /*
-        * Adds a child
-        * @param child: the action to add as child
-        */
-        Action.prototype.addChild = function (child) {
-            if (child === null) {
-                return false;
-            }
-            this.children.push(child);
-            child.parent = this;
-            return true;
-        };
-        /*
-        * Removes the given action to children
-        * @param child: the child to remove
-        */
-        Action.prototype.removeChild = function (child) {
-            var indice = this.children.indexOf(child);
-            if (indice !== -1) {
-                this.children.splice(indice, 1);
-                return true;
-            }
-            return false;
-        };
-        /*
-        * Clears the children's array
-        */
-        Action.prototype.clearChildren = function () {
-            this.children = new Array();
-        };
-        return Action;
-    })();
-    ActionsBuilder.Action = Action;
-})(ActionsBuilder || (ActionsBuilder = {}));
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    var Node = (function () {
+        function Node() {
+            this.rect = null;
+            this.text = null;
+            this.line = null;
+            this.detached = false;
+            this.minimized = false;
+        }
+        /**
+        * Returns if the point (x, y) is inside the text or rect
+        * @param x: the x position of the point
+        * @param y: the y position of the point
+        */
+        Node.prototype.isPointInside = function (x, y) {
+            return this.rect.isPointInside(x, y) || this.text.isPointInside(x, y);
+        };
+        return Node;
+    }());
+    ActionsBuilder.Node = Node;
+    var Action = (function () {
+        /**
+        * Constructor
+        * @param node: The associated node to draw in the viewer
+        */
+        function Action(node) {
+            this.parent = null;
+            this.children = new Array();
+            this.name = "";
+            this.type = ActionsBuilder.Type.OBJECT;
+            this.properties = new Array();
+            this.propertiesResults = new Array();
+            this.combineArray = null;
+            this.hub = null;
+            this.combineAction = null;
+            this.node = node;
+        }
+        /*
+        * Removes a combined action from the combine array
+        * @param action: the action to remove
+        */
+        Action.prototype.removeCombinedAction = function (action) {
+            if (action === null || this.combineArray === null) {
+                return false;
+            }
+            var index = this.combineArray.indexOf(action);
+            if (index !== -1) {
+                this.combineArray.splice(index, 1);
+            }
+            return false;
+        };
+        /*
+        * Adds a child
+        * @param child: the action to add as child
+        */
+        Action.prototype.addChild = function (child) {
+            if (child === null) {
+                return false;
+            }
+            this.children.push(child);
+            child.parent = this;
+            return true;
+        };
+        /*
+        * Removes the given action to children
+        * @param child: the child to remove
+        */
+        Action.prototype.removeChild = function (child) {
+            var indice = this.children.indexOf(child);
+            if (indice !== -1) {
+                this.children.splice(indice, 1);
+                return true;
+            }
+            return false;
+        };
+        /*
+        * Clears the children's array
+        */
+        Action.prototype.clearChildren = function () {
+            this.children = new Array();
+        };
+        return Action;
+    }());
+    ActionsBuilder.Action = Action;
+})(ActionsBuilder || (ActionsBuilder = {}));
 //# sourceMappingURL=actionsbuilder.actionNode.js.map

+ 118 - 118
Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.contextMenu.js

@@ -1,119 +1,119 @@
-var ActionsBuilder;
-(function (ActionsBuilder) {
-    var ContextMenu = (function () {
-        /*
-        * Constructor
-        * @param viewer: the graph viewer
-        */
-        function ContextMenu(viewer) {
-            this.showing = false;
-            this.savedColor = Raphael.rgb(255, 255, 255);
-            this.overColor = Raphael.rgb(140, 200, 230);
-            this._viewer = null;
-            this.elements = [
-                { text: "Reduce", node: null, action: "onReduce" },
-                { text: "Delete", node: null, action: "onRemoveNode" },
-                { text: "Delete branch", node: null, action: "onRemoveBranch" },
-                { text: "Connect / Disconnect", node: null, action: "onDetachAction" },
-                { text: "Copy", node: null, action: "onCopyStructure" },
-                { text: "Paste", node: null, action: "onPasteStructure" },
-                // Add other elements here
-                { text: "", node: null, action: null } // Color separator (top)
-            ];
-            // Members
-            this._viewer = viewer;
-            // Configure
-            this.attachControl(this._viewer.paper.canvas);
-        }
-        ContextMenu.prototype.attachControl = function (element) {
-            var _this = this;
-            var onClick = function (event) {
-                var x = _this._viewer.mousex;
-                var y = _this._viewer.mousey;
-                // Remove all context menu nodes, and run action if selected
-                if (_this.showing) {
-                    for (var i = 0; i < _this.elements.length; i++) {
-                        var element = _this.elements[i];
-                        if (element.action && element.node.rect.isPointInside(x, y)) {
-                            _this._viewer.utils[element.action]();
-                            _this._viewer.update();
-                        }
-                        element.node.rect.remove();
-                        element.node.text.remove();
-                    }
-                }
-                _this.showing = false;
-            };
-            var onMouseMove = function (event) {
-                // Override context menu's node color if mouse is inside
-                if (_this.showing) {
-                    for (var i = 0; i < _this.elements.length; i++) {
-                        var element = _this.elements[i];
-                        if (element.text === "")
-                            continue;
-                        var x = _this._viewer.mousex;
-                        var y = _this._viewer.mousey;
-                        if (element.node.rect.isPointInside(x, y)) {
-                            element.node.rect.attr("fill", _this.overColor);
-                        }
-                        else {
-                            element.node.rect.attr("fill", _this.savedColor);
-                        }
-                    }
-                }
-            };
-            var onRightClick = function (event) {
-                var x = _this._viewer.mousex;
-                var y = _this._viewer.mousey;
-                _this._viewer.onClick(event);
-                // Set selected node
-                var result = _this._viewer.traverseGraph(null, x, y, true);
-                if (result.hit) {
-                }
-                // Properly draw the context menu on the screen
-                if (y + (ActionsBuilder.Viewer.NODE_HEIGHT * _this.elements.length) > _this._viewer.viewerElement.offsetHeight + _this._viewer.viewerElement.scrollTop) {
-                    y = (ActionsBuilder.Viewer.NODE_HEIGHT * _this.elements.length);
-                }
-                if (x + ActionsBuilder.Viewer.NODE_WIDTH > _this._viewer.viewerElement.offsetWidth + _this._viewer.viewerElement.scrollLeft) {
-                    x -= ActionsBuilder.Viewer.NODE_WIDTH;
-                }
-                if (!_this.showing) {
-                    if (_this._viewer.selectedNode === null)
-                        return;
-                    // Create elements
-                    var yOffset = 10;
-                    for (var i = 0; i < _this.elements.length - 1; i++) {
-                        var element = _this.elements[i];
-                        element.node = _this._viewer._createNode(element.text, ActionsBuilder.Type.OBJECT, true);
-                        element.node.rect.attr("fill", Raphael.rgb(216, 216, 216));
-                        element.node.rect.attr("x", x);
-                        element.node.rect.attr("y", y + yOffset);
-                        element.node.text.attr("x", x + 5);
-                        element.node.text.attr("y", y + yOffset + element.node.rect.attr("height") / 2);
-                        yOffset += ActionsBuilder.Viewer.NODE_HEIGHT;
-                    }
-                    // Color separator
-                    var separator = _this.elements[_this.elements.length - 1];
-                    separator.node = _this._viewer._createNode("", ActionsBuilder.Type.OBJECT, true);
-                    separator.node.rect.attr("fill", _this._viewer.getNodeColor(_this._viewer.selectedNode.type, _this._viewer.selectedNode.node.detached));
-                    separator.node.rect.attr("x", x);
-                    separator.node.rect.attr("y", y);
-                    separator.node.rect.attr("height", 10);
-                    // Finish
-                    _this.showing = true;
-                }
-                else {
-                    onClick(event);
-                    onRightClick(event);
-                }
-                window.event.returnValue = false;
-            };
-            document.addEventListener("click", onClick);
-            document.addEventListener("mousemove", onMouseMove);
-            element.addEventListener("contextmenu", onRightClick);
-        };
-        return ContextMenu;
-    })();
-    ActionsBuilder.ContextMenu = ContextMenu;
-})(ActionsBuilder || (ActionsBuilder = {}));
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    var ContextMenu = (function () {
+        /*
+        * Constructor
+        * @param viewer: the graph viewer
+        */
+        function ContextMenu(viewer) {
+            this.showing = false;
+            this.savedColor = Raphael.rgb(255, 255, 255);
+            this.overColor = Raphael.rgb(140, 200, 230);
+            this._viewer = null;
+            this.elements = [
+                { text: "Reduce", node: null, action: "onReduce" },
+                { text: "Delete", node: null, action: "onRemoveNode" },
+                { text: "Delete branch", node: null, action: "onRemoveBranch" },
+                { text: "Connect / Disconnect", node: null, action: "onDetachAction" },
+                { text: "Copy", node: null, action: "onCopyStructure" },
+                { text: "Paste", node: null, action: "onPasteStructure" },
+                // Add other elements here
+                { text: "", node: null, action: null } // Color separator (top)
+            ];
+            // Members
+            this._viewer = viewer;
+            // Configure
+            this.attachControl(this._viewer.paper.canvas);
+        }
+        ContextMenu.prototype.attachControl = function (element) {
+            var _this = this;
+            var onClick = function (event) {
+                var x = _this._viewer.mousex;
+                var y = _this._viewer.mousey;
+                // Remove all context menu nodes, and run action if selected
+                if (_this.showing) {
+                    for (var i = 0; i < _this.elements.length; i++) {
+                        var element = _this.elements[i];
+                        if (element.action && element.node.rect.isPointInside(x, y)) {
+                            _this._viewer.utils[element.action]();
+                            _this._viewer.update();
+                        }
+                        element.node.rect.remove();
+                        element.node.text.remove();
+                    }
+                }
+                _this.showing = false;
+            };
+            var onMouseMove = function (event) {
+                // Override context menu's node color if mouse is inside
+                if (_this.showing) {
+                    for (var i = 0; i < _this.elements.length; i++) {
+                        var element = _this.elements[i];
+                        if (element.text === "")
+                            continue;
+                        var x = _this._viewer.mousex;
+                        var y = _this._viewer.mousey;
+                        if (element.node.rect.isPointInside(x, y)) {
+                            element.node.rect.attr("fill", _this.overColor);
+                        }
+                        else {
+                            element.node.rect.attr("fill", _this.savedColor);
+                        }
+                    }
+                }
+            };
+            var onRightClick = function (event) {
+                var x = _this._viewer.mousex;
+                var y = _this._viewer.mousey;
+                _this._viewer.onClick(event);
+                // Set selected node
+                var result = _this._viewer.traverseGraph(null, x, y, true);
+                if (result.hit) {
+                }
+                // Properly draw the context menu on the screen
+                if (y + (ActionsBuilder.Viewer.NODE_HEIGHT * _this.elements.length) > _this._viewer.viewerElement.offsetHeight + _this._viewer.viewerElement.scrollTop) {
+                    y = (ActionsBuilder.Viewer.NODE_HEIGHT * _this.elements.length);
+                }
+                if (x + ActionsBuilder.Viewer.NODE_WIDTH > _this._viewer.viewerElement.offsetWidth + _this._viewer.viewerElement.scrollLeft) {
+                    x -= ActionsBuilder.Viewer.NODE_WIDTH;
+                }
+                if (!_this.showing) {
+                    if (_this._viewer.selectedNode === null)
+                        return;
+                    // Create elements
+                    var yOffset = 10;
+                    for (var i = 0; i < _this.elements.length - 1; i++) {
+                        var element = _this.elements[i];
+                        element.node = _this._viewer._createNode(element.text, ActionsBuilder.Type.OBJECT, true);
+                        element.node.rect.attr("fill", Raphael.rgb(216, 216, 216));
+                        element.node.rect.attr("x", x);
+                        element.node.rect.attr("y", y + yOffset);
+                        element.node.text.attr("x", x + 5);
+                        element.node.text.attr("y", y + yOffset + element.node.rect.attr("height") / 2);
+                        yOffset += ActionsBuilder.Viewer.NODE_HEIGHT;
+                    }
+                    // Color separator
+                    var separator = _this.elements[_this.elements.length - 1];
+                    separator.node = _this._viewer._createNode("", ActionsBuilder.Type.OBJECT, true);
+                    separator.node.rect.attr("fill", _this._viewer.getNodeColor(_this._viewer.selectedNode.type, _this._viewer.selectedNode.node.detached));
+                    separator.node.rect.attr("x", x);
+                    separator.node.rect.attr("y", y);
+                    separator.node.rect.attr("height", 10);
+                    // Finish
+                    _this.showing = true;
+                }
+                else {
+                    onClick(event);
+                    onRightClick(event);
+                }
+                window.event.returnValue = false;
+            };
+            document.addEventListener("click", onClick);
+            document.addEventListener("mousemove", onMouseMove);
+            element.addEventListener("contextmenu", onRightClick);
+        };
+        return ContextMenu;
+    }());
+    ActionsBuilder.ContextMenu = ContextMenu;
+})(ActionsBuilder || (ActionsBuilder = {}));
 //# sourceMappingURL=actionsbuilder.contextMenu.js.map

+ 351 - 351
Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.js

@@ -1,352 +1,352 @@
-var ActionsBuilder;
-(function (ActionsBuilder) {
-    /**
-    * Defines static types
-    */
-    var Type = (function () {
-        function Type() {
-        }
-        Object.defineProperty(Type, "TRIGGER", {
-            get: function () {
-                return Type._TRIGGER;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(Type, "ACTION", {
-            get: function () {
-                return Type._ACTION;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(Type, "FLOW_CONTROL", {
-            get: function () {
-                return Type._FLOW_CONTROL;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(Type, "OBJECT", {
-            get: function () {
-                return Type._OBJECT;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(Type, "SCENE", {
-            get: function () {
-                return Type._SCENE;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Type._TRIGGER = 0;
-        Type._ACTION = 1;
-        Type._FLOW_CONTROL = 2;
-        Type._OBJECT = 3;
-        Type._SCENE = 4;
-        return Type;
-    })();
-    ActionsBuilder.Type = Type;
-    /*
-    * Defines the BABYLON.JS elements
-    */
-    var SceneElements = (function () {
-        function SceneElements() {
-        }
-        Object.defineProperty(SceneElements, "ENGINE", {
-            get: function () {
-                return SceneElements._ENGINE;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "SCENE", {
-            get: function () {
-                return SceneElements._SCENE;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "MESH", {
-            get: function () {
-                return SceneElements._MESH;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "LIGHT", {
-            get: function () {
-                return SceneElements._LIGHT;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "CAMERA", {
-            get: function () {
-                return SceneElements._CAMERA;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "MESHES", {
-            get: function () {
-                return SceneElements._MESHES;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "LIGHTS", {
-            get: function () {
-                return SceneElements._LIGHTS;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "CAMERAS", {
-            get: function () {
-                return SceneElements._CAMERAS;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "SOUNDS", {
-            get: function () {
-                return SceneElements._SOUNDS;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "MESH_PROPERTIES", {
-            get: function () {
-                return SceneElements._MESH_PROPERTIES;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "LIGHT_PROPERTIES", {
-            get: function () {
-                return SceneElements._LIGHT_PROPERTIES;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "CAMERA_PROPERTIES", {
-            get: function () {
-                return SceneElements._CAMERA_PROPERTIES;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "SCENE_PROPERTIES", {
-            get: function () {
-                return SceneElements._SCENE_PROPERTIES;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "TYPES", {
-            get: function () {
-                return SceneElements._TYPES;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(SceneElements, "OPERATORS", {
-            get: function () {
-                return SceneElements._OPERATORS;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        /*
-        * Methods
-        */
-        SceneElements.GetInstanceOf = function (object) {
-            if (object === null || object === undefined) {
-                return "";
-            }
-            return object.constructor.toString().match(/function (\w*)/)[1];
-        };
-        SceneElements.TestInstanceOf = function (object, propertyName) {
-            if (object === null || object.constructor === null) {
-                return false;
-            }
-            if (propertyName.length > 0 && propertyName[0] === "_")
-                return false;
-            var name = SceneElements.GetInstanceOf(object);
-            for (var i = 0; i < SceneElements.TYPES.length; i++) {
-                if (name === SceneElements.TYPES[i]) {
-                    return true;
-                }
-            }
-            return false;
-        };
-        /*
-        * BabylonJS objects
-        */
-        SceneElements._ENGINE = new BABYLON.Engine(document.getElementById("RenderCanvasID"));
-        SceneElements._SCENE = new BABYLON.Scene(SceneElements.ENGINE);
-        SceneElements._MESH = new BABYLON.Mesh("mesh", SceneElements._SCENE);
-        SceneElements._LIGHT = new BABYLON.Light("light", SceneElements._SCENE);
-        SceneElements._CAMERA = new BABYLON.Camera("camera", BABYLON.Vector3.Zero(), SceneElements._SCENE);
-        /*
-        * Objects names
-        */
-        SceneElements._MESHES = new Array();
-        SceneElements._LIGHTS = new Array();
-        SceneElements._CAMERAS = new Array();
-        SceneElements._SOUNDS = new Array();
-        /*
-        * Properties
-        */
-        SceneElements._MESH_PROPERTIES = new Array();
-        SceneElements._LIGHT_PROPERTIES = new Array();
-        SceneElements._CAMERA_PROPERTIES = new Array();
-        SceneElements._SCENE_PROPERTIES = new Array();
-        /*
-        * Types
-        */
-        SceneElements._TYPES = new Array();
-        /*
-        * Operators
-        */
-        SceneElements._OPERATORS = new Array();
-        return SceneElements;
-    })();
-    ActionsBuilder.SceneElements = SceneElements;
-    // Functions
-    var specialTypes = [
-        "StandardMaterial"
-    ];
-    SceneElements.MESH.material = new BABYLON.StandardMaterial("material", SceneElements.SCENE);
-    var addSpecialType = function (object, properties, thing) {
-        for (var specialThing in object[thing]) {
-            if (object[thing].hasOwnProperty(specialThing) && SceneElements.TestInstanceOf(object[thing][specialThing], specialThing)) {
-                properties.push(thing + "." + specialThing);
-            }
-        }
-    };
-    // Configure types
-    SceneElements.TYPES.push("Color3");
-    SceneElements.TYPES.push("Boolean");
-    SceneElements.TYPES.push("Number");
-    SceneElements.TYPES.push("Vector2");
-    SceneElements.TYPES.push("Vector3");
-    SceneElements.TYPES.push("String");
-    // Configure operators
-    SceneElements.OPERATORS.push("IsEqual");
-    SceneElements.OPERATORS.push("IsDifferent");
-    SceneElements.OPERATORS.push("IsGreater");
-    SceneElements.OPERATORS.push("IsLesser");
-    // Configure properties
-    for (var thing in SceneElements.MESH) {
-        var instance = SceneElements.GetInstanceOf(SceneElements.MESH[thing]);
-        if (SceneElements.MESH.hasOwnProperty(thing)) {
-            if (specialTypes.indexOf(instance) !== -1) {
-                addSpecialType(SceneElements.MESH, SceneElements.MESH_PROPERTIES, thing);
-            }
-            else if (SceneElements.TestInstanceOf(SceneElements.MESH[thing], thing)) {
-                SceneElements.MESH_PROPERTIES.push(thing);
-            }
-        }
-    }
-    for (var thing in SceneElements.LIGHT) {
-        if (SceneElements.LIGHT.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.LIGHT[thing], thing)) {
-            SceneElements.LIGHT_PROPERTIES.push(thing);
-        }
-    }
-    for (var thing in SceneElements.CAMERA) {
-        if (SceneElements.CAMERA.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.CAMERA[thing], thing)) {
-            SceneElements.CAMERA_PROPERTIES.push(thing);
-        }
-    }
-    for (var thing in SceneElements.SCENE) {
-        if (SceneElements.SCENE.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.SCENE[thing], thing)) {
-            SceneElements.SCENE_PROPERTIES.push(thing);
-        }
-    }
-    /**
-    * Actions Builder elements (triggers, actions & flow controls) that are
-    * arrays of Element
-    */
-    var Elements = (function () {
-        function Elements() {
-        }
-        Object.defineProperty(Elements, "TRIGGERS", {
-            get: function () {
-                return Elements._TRIGGERS;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(Elements, "ACTIONS", {
-            get: function () {
-                return Elements._ACTIONS;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(Elements, "FLOW_CONTROLS", {
-            get: function () {
-                return Elements._FLOW_CONTROLS;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Elements.GetElementFromName = function (name) {
-            for (var i = 0; i < Elements.TRIGGERS.length; i++) {
-                if (Elements.TRIGGERS[i].name === name) {
-                    return Elements._TRIGGERS[i];
-                }
-            }
-            for (var i = 0; i < Elements.ACTIONS.length; i++) {
-                if (Elements.ACTIONS[i].name === name) {
-                    return Elements._ACTIONS[i];
-                }
-            }
-            for (var i = 0; i < Elements.FLOW_CONTROLS.length; i++) {
-                if (Elements.FLOW_CONTROLS[i].name === name) {
-                    return Elements._FLOW_CONTROLS[i];
-                }
-            }
-            return null;
-        };
-        Elements._TRIGGERS = new Array();
-        Elements._ACTIONS = new Array();
-        Elements._FLOW_CONTROLS = new Array();
-        return Elements;
-    })();
-    ActionsBuilder.Elements = Elements;
-    // Configure triggers
-    Elements.TRIGGERS.push({ name: "OnPickTrigger", text: "pick", properties: [], description: "When the user picks the edited mesh" });
-    Elements.TRIGGERS.push({ name: "OnLeftPickTrigger", text: "left pick", properties: [], description: "When the user picks the edited mesh using the left click" });
-    Elements.TRIGGERS.push({ name: "OnRightPickTrigger", text: "right pick", properties: [], description: "When the user picks the edited mesh using the right click" });
-    Elements.TRIGGERS.push({ name: "OnCenterPickTrigger", text: "center pick", properties: [], description: "When the user picks the edited mesh using the click of the mouse wheel" });
-    Elements.TRIGGERS.push({ name: "OnPointerOverTrigger", text: "pointer over", properties: [], description: "When the user's mouse is over the edited mesh" });
-    Elements.TRIGGERS.push({ name: "OnPointerOutTrigger", text: "pointer out", properties: [], description: "When the user's mouse is out of the edited mesh" });
-    Elements.TRIGGERS.push({ name: "OnEveryFrameTrigger", text: "every frame", properties: [], description: "This trigger is called each frame (only on scene)" });
-    Elements.TRIGGERS.push({ name: "OnIntersectionEnterTrigger", text: "intersection enter", properties: [{ targetType: "MeshProperties", text: "parameter", value: "Object name?" }], description: "When the edited mesh intersects the another mesh predefined in the options" });
-    Elements.TRIGGERS.push({ name: "OnIntersectionExitTrigger", text: "intersection exit", properties: [{ targetType: "MeshProperties", text: "parameter", value: "Object name?" }], description: "When the edited mesh exits intersection with the another mesh predefined in the options" });
-    Elements.TRIGGERS.push({ name: "OnKeyDownTrigger", text: "key down", properties: [{ targetType: null, text: "parameter:", value: "a" }], description: "When the user pressed a key (enter the key character, example: \"r\")" });
-    Elements.TRIGGERS.push({ name: "OnKeyUpTrigger", text: "key up", properties: [{ targetType: null, text: "parameter:", value: "a" }], description: "When the user unpressed a key (enter the key character, example: \"p\")" });
-    // Configure actions
-    Elements.ACTIONS.push({ name: "SwitchBooleanAction", text: "switch boolean", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }], description: "Switches the boolean value of a given parameter of the target object: true to false, or false to true" });
-    Elements.ACTIONS.push({ name: "SetStateAction", text: "set state", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "value", value: "" }], description: "Sets a new state value for the target object (example: \"off\" or \"on\")" });
-    Elements.ACTIONS.push({ name: "SetValueAction", text: "set value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }], description: "Sets a new value to the specified parameter of the target object (example: position.x to 0.0)" });
-    Elements.ACTIONS.push({ name: "SetParentAction", text: "set parent", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "parent", value: "" }], description: "Sets the new parent of the target object (example: a mesh or a light)" });
-    Elements.ACTIONS.push({ name: "IncrementValueAction", text: "increment value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }], description: "Increments the value of the given parameter of the target object. The value can be negative. (example: increment position.x of 5.0)" });
-    Elements.ACTIONS.push({ name: "PlayAnimationAction", text: "play animation", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "from", value: "0" }, { text: "to", value: "150" }, { text: "loop", value: "false" }], description: "Plays an animation of the target object. Specify the start frame, the end frame and if the animation should loop." });
-    Elements.ACTIONS.push({ name: "StopAnimationAction", text: "stop animation", properties: [{ targetType: "MeshProperties", text: "target", value: "" }], description: "Stops the animations of the target object." });
-    Elements.ACTIONS.push({ name: "DoNothingAction", text: "do nothing", properties: [], description: "Does nothing, can be used to balance/equilibrate the actions graph." });
-    Elements.ACTIONS.push({ name: "InterpolateValueAction", text: "interpolate value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "0" }, { text: "duration", value: "1000" }, { text: "stopOtherAnimations", value: "false" }], description: "Creates an animation (key frames) that animates the target object by interpolating the given parameter of the target value." });
-    Elements.ACTIONS.push({ name: "PlaySoundAction", text: "play sound", properties: [{ text: "sound", value: "" }], description: "Plays the specified sound." });
-    Elements.ACTIONS.push({ name: "StopSoundAction", text: "stop sound", properties: [{ text: "sound", value: "" }], description: "Stops the specified sound." });
-    Elements.ACTIONS.push({ name: "CombineAction", text: "combine", properties: [], description: "Special action that combines multiple actions. The combined actions are executed at the same time. Drag'n'drop the new actions inside to combine actions." });
-    // Configure flow control
-    Elements.FLOW_CONTROLS.push({ name: "ValueCondition", text: "value condition", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }, { text: "operator", value: SceneElements.OPERATORS[0] }], description: "A condition checking if a given value is equal, different, lesser or greater than the given parameter of the target object" });
-    Elements.FLOW_CONTROLS.push({ name: "StateCondition", text: "state condition", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "value", value: "" }], description: "A condition checking if the target object's state is equal to the given state. See \"set state\" action to set a state to an object." });
-    Elements.FLOW_CONTROLS.push({ name: "Hub", text: "hub", properties: [], description: "The hub is internally used by the Combine Action. It allows to add children to the Combine Action" });
-})(ActionsBuilder || (ActionsBuilder = {}));
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    /**
+    * Defines static types
+    */
+    var Type = (function () {
+        function Type() {
+        }
+        Object.defineProperty(Type, "TRIGGER", {
+            get: function () {
+                return Type._TRIGGER;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Type, "ACTION", {
+            get: function () {
+                return Type._ACTION;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Type, "FLOW_CONTROL", {
+            get: function () {
+                return Type._FLOW_CONTROL;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Type, "OBJECT", {
+            get: function () {
+                return Type._OBJECT;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Type, "SCENE", {
+            get: function () {
+                return Type._SCENE;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        return Type;
+    }());
+    Type._TRIGGER = 0;
+    Type._ACTION = 1;
+    Type._FLOW_CONTROL = 2;
+    Type._OBJECT = 3;
+    Type._SCENE = 4;
+    ActionsBuilder.Type = Type;
+    /*
+    * Defines the BABYLON.JS elements
+    */
+    var SceneElements = (function () {
+        function SceneElements() {
+        }
+        Object.defineProperty(SceneElements, "ENGINE", {
+            get: function () {
+                return SceneElements._ENGINE;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "SCENE", {
+            get: function () {
+                return SceneElements._SCENE;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "MESH", {
+            get: function () {
+                return SceneElements._MESH;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "LIGHT", {
+            get: function () {
+                return SceneElements._LIGHT;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "CAMERA", {
+            get: function () {
+                return SceneElements._CAMERA;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "MESHES", {
+            get: function () {
+                return SceneElements._MESHES;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "LIGHTS", {
+            get: function () {
+                return SceneElements._LIGHTS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "CAMERAS", {
+            get: function () {
+                return SceneElements._CAMERAS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "SOUNDS", {
+            get: function () {
+                return SceneElements._SOUNDS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "MESH_PROPERTIES", {
+            get: function () {
+                return SceneElements._MESH_PROPERTIES;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "LIGHT_PROPERTIES", {
+            get: function () {
+                return SceneElements._LIGHT_PROPERTIES;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "CAMERA_PROPERTIES", {
+            get: function () {
+                return SceneElements._CAMERA_PROPERTIES;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "SCENE_PROPERTIES", {
+            get: function () {
+                return SceneElements._SCENE_PROPERTIES;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "TYPES", {
+            get: function () {
+                return SceneElements._TYPES;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "OPERATORS", {
+            get: function () {
+                return SceneElements._OPERATORS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        /*
+        * Methods
+        */
+        SceneElements.GetInstanceOf = function (object) {
+            if (object === null || object === undefined) {
+                return "";
+            }
+            return object.constructor.toString().match(/function (\w*)/)[1];
+        };
+        SceneElements.TestInstanceOf = function (object, propertyName) {
+            if (object === null || object.constructor === null) {
+                return false;
+            }
+            if (propertyName.length > 0 && propertyName[0] === "_")
+                return false;
+            var name = SceneElements.GetInstanceOf(object);
+            for (var i = 0; i < SceneElements.TYPES.length; i++) {
+                if (name === SceneElements.TYPES[i]) {
+                    return true;
+                }
+            }
+            return false;
+        };
+        return SceneElements;
+    }());
+    /*
+    * BabylonJS objects
+    */
+    SceneElements._ENGINE = new BABYLON.Engine(document.getElementById("RenderCanvasID"));
+    SceneElements._SCENE = new BABYLON.Scene(SceneElements.ENGINE);
+    SceneElements._MESH = new BABYLON.Mesh("mesh", SceneElements._SCENE);
+    SceneElements._LIGHT = new BABYLON.Light("light", SceneElements._SCENE);
+    SceneElements._CAMERA = new BABYLON.Camera("camera", BABYLON.Vector3.Zero(), SceneElements._SCENE);
+    /*
+    * Objects names
+    */
+    SceneElements._MESHES = new Array();
+    SceneElements._LIGHTS = new Array();
+    SceneElements._CAMERAS = new Array();
+    SceneElements._SOUNDS = new Array();
+    /*
+    * Properties
+    */
+    SceneElements._MESH_PROPERTIES = new Array();
+    SceneElements._LIGHT_PROPERTIES = new Array();
+    SceneElements._CAMERA_PROPERTIES = new Array();
+    SceneElements._SCENE_PROPERTIES = new Array();
+    /*
+    * Types
+    */
+    SceneElements._TYPES = new Array();
+    /*
+    * Operators
+    */
+    SceneElements._OPERATORS = new Array();
+    ActionsBuilder.SceneElements = SceneElements;
+    // Functions
+    var specialTypes = [
+        "StandardMaterial"
+    ];
+    SceneElements.MESH.material = new BABYLON.StandardMaterial("material", SceneElements.SCENE);
+    var addSpecialType = function (object, properties, thing) {
+        for (var specialThing in object[thing]) {
+            if (object[thing].hasOwnProperty(specialThing) && SceneElements.TestInstanceOf(object[thing][specialThing], specialThing)) {
+                properties.push(thing + "." + specialThing);
+            }
+        }
+    };
+    // Configure types
+    SceneElements.TYPES.push("Color3");
+    SceneElements.TYPES.push("Boolean");
+    SceneElements.TYPES.push("Number");
+    SceneElements.TYPES.push("Vector2");
+    SceneElements.TYPES.push("Vector3");
+    SceneElements.TYPES.push("String");
+    // Configure operators
+    SceneElements.OPERATORS.push("IsEqual");
+    SceneElements.OPERATORS.push("IsDifferent");
+    SceneElements.OPERATORS.push("IsGreater");
+    SceneElements.OPERATORS.push("IsLesser");
+    // Configure properties
+    for (var thing in SceneElements.MESH) {
+        var instance = SceneElements.GetInstanceOf(SceneElements.MESH[thing]);
+        if (SceneElements.MESH.hasOwnProperty(thing)) {
+            if (specialTypes.indexOf(instance) !== -1) {
+                addSpecialType(SceneElements.MESH, SceneElements.MESH_PROPERTIES, thing);
+            }
+            else if (SceneElements.TestInstanceOf(SceneElements.MESH[thing], thing)) {
+                SceneElements.MESH_PROPERTIES.push(thing);
+            }
+        }
+    }
+    for (var thing in SceneElements.LIGHT) {
+        if (SceneElements.LIGHT.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.LIGHT[thing], thing)) {
+            SceneElements.LIGHT_PROPERTIES.push(thing);
+        }
+    }
+    for (var thing in SceneElements.CAMERA) {
+        if (SceneElements.CAMERA.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.CAMERA[thing], thing)) {
+            SceneElements.CAMERA_PROPERTIES.push(thing);
+        }
+    }
+    for (var thing in SceneElements.SCENE) {
+        if (SceneElements.SCENE.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.SCENE[thing], thing)) {
+            SceneElements.SCENE_PROPERTIES.push(thing);
+        }
+    }
+    /**
+    * Actions Builder elements (triggers, actions & flow controls) that are
+    * arrays of Element
+    */
+    var Elements = (function () {
+        function Elements() {
+        }
+        Object.defineProperty(Elements, "TRIGGERS", {
+            get: function () {
+                return Elements._TRIGGERS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Elements, "ACTIONS", {
+            get: function () {
+                return Elements._ACTIONS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Elements, "FLOW_CONTROLS", {
+            get: function () {
+                return Elements._FLOW_CONTROLS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Elements.GetElementFromName = function (name) {
+            for (var i = 0; i < Elements.TRIGGERS.length; i++) {
+                if (Elements.TRIGGERS[i].name === name) {
+                    return Elements._TRIGGERS[i];
+                }
+            }
+            for (var i = 0; i < Elements.ACTIONS.length; i++) {
+                if (Elements.ACTIONS[i].name === name) {
+                    return Elements._ACTIONS[i];
+                }
+            }
+            for (var i = 0; i < Elements.FLOW_CONTROLS.length; i++) {
+                if (Elements.FLOW_CONTROLS[i].name === name) {
+                    return Elements._FLOW_CONTROLS[i];
+                }
+            }
+            return null;
+        };
+        return Elements;
+    }());
+    Elements._TRIGGERS = new Array();
+    Elements._ACTIONS = new Array();
+    Elements._FLOW_CONTROLS = new Array();
+    ActionsBuilder.Elements = Elements;
+    // Configure triggers
+    Elements.TRIGGERS.push({ name: "OnPickTrigger", text: "pick", properties: [], description: "When the user picks the edited mesh" });
+    Elements.TRIGGERS.push({ name: "OnLeftPickTrigger", text: "left pick", properties: [], description: "When the user picks the edited mesh using the left click" });
+    Elements.TRIGGERS.push({ name: "OnRightPickTrigger", text: "right pick", properties: [], description: "When the user picks the edited mesh using the right click" });
+    Elements.TRIGGERS.push({ name: "OnCenterPickTrigger", text: "center pick", properties: [], description: "When the user picks the edited mesh using the click of the mouse wheel" });
+    Elements.TRIGGERS.push({ name: "OnPointerOverTrigger", text: "pointer over", properties: [], description: "When the user's mouse is over the edited mesh" });
+    Elements.TRIGGERS.push({ name: "OnPointerOutTrigger", text: "pointer out", properties: [], description: "When the user's mouse is out of the edited mesh" });
+    Elements.TRIGGERS.push({ name: "OnEveryFrameTrigger", text: "every frame", properties: [], description: "This trigger is called each frame (only on scene)" });
+    Elements.TRIGGERS.push({ name: "OnIntersectionEnterTrigger", text: "intersection enter", properties: [{ targetType: "MeshProperties", text: "parameter", value: "Object name?" }], description: "When the edited mesh intersects the another mesh predefined in the options" });
+    Elements.TRIGGERS.push({ name: "OnIntersectionExitTrigger", text: "intersection exit", properties: [{ targetType: "MeshProperties", text: "parameter", value: "Object name?" }], description: "When the edited mesh exits intersection with the another mesh predefined in the options" });
+    Elements.TRIGGERS.push({ name: "OnKeyDownTrigger", text: "key down", properties: [{ targetType: null, text: "parameter", value: "a" }], description: "When the user pressed a key (enter the key character, example: \"r\")" });
+    Elements.TRIGGERS.push({ name: "OnKeyUpTrigger", text: "key up", properties: [{ targetType: null, text: "parameter", value: "a" }], description: "When the user unpressed a key (enter the key character, example: \"p\")" });
+    // Configure actions
+    Elements.ACTIONS.push({ name: "SwitchBooleanAction", text: "switch boolean", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }], description: "Switches the boolean value of a given parameter of the target object: true to false, or false to true" });
+    Elements.ACTIONS.push({ name: "SetStateAction", text: "set state", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "value", value: "" }], description: "Sets a new state value for the target object (example: \"off\" or \"on\")" });
+    Elements.ACTIONS.push({ name: "SetValueAction", text: "set value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }], description: "Sets a new value to the specified parameter of the target object (example: position.x to 0.0)" });
+    Elements.ACTIONS.push({ name: "SetParentAction", text: "set parent", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "parent", value: "" }], description: "Sets the new parent of the target object (example: a mesh or a light)" });
+    Elements.ACTIONS.push({ name: "IncrementValueAction", text: "increment value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }], description: "Increments the value of the given parameter of the target object. The value can be negative. (example: increment position.x of 5.0)" });
+    Elements.ACTIONS.push({ name: "PlayAnimationAction", text: "play animation", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "from", value: "0" }, { text: "to", value: "150" }, { text: "loop", value: "false" }], description: "Plays an animation of the target object. Specify the start frame, the end frame and if the animation should loop." });
+    Elements.ACTIONS.push({ name: "StopAnimationAction", text: "stop animation", properties: [{ targetType: "MeshProperties", text: "target", value: "" }], description: "Stops the animations of the target object." });
+    Elements.ACTIONS.push({ name: "DoNothingAction", text: "do nothing", properties: [], description: "Does nothing, can be used to balance/equilibrate the actions graph." });
+    Elements.ACTIONS.push({ name: "InterpolateValueAction", text: "interpolate value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "0" }, { text: "duration", value: "1000" }, { text: "stopOtherAnimations", value: "false" }], description: "Creates an animation (key frames) that animates the target object by interpolating the given parameter of the target value." });
+    Elements.ACTIONS.push({ name: "PlaySoundAction", text: "play sound", properties: [{ text: "sound", value: "" }], description: "Plays the specified sound." });
+    Elements.ACTIONS.push({ name: "StopSoundAction", text: "stop sound", properties: [{ text: "sound", value: "" }], description: "Stops the specified sound." });
+    Elements.ACTIONS.push({ name: "CombineAction", text: "combine", properties: [], description: "Special action that combines multiple actions. The combined actions are executed at the same time. Drag'n'drop the new actions inside to combine actions." });
+    // Configure flow control
+    Elements.FLOW_CONTROLS.push({ name: "ValueCondition", text: "value condition", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }, { text: "operator", value: SceneElements.OPERATORS[0] }], description: "A condition checking if a given value is equal, different, lesser or greater than the given parameter of the target object" });
+    Elements.FLOW_CONTROLS.push({ name: "StateCondition", text: "state condition", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "value", value: "" }], description: "A condition checking if the target object's state is equal to the given state. See \"set state\" action to set a state to an object." });
+    Elements.FLOW_CONTROLS.push({ name: "Hub", text: "hub", properties: [], description: "The hub is internally used by the Combine Action. It allows to add children to the Combine Action" });
+})(ActionsBuilder || (ActionsBuilder = {}));
 //# sourceMappingURL=actionsbuilder.js.map

+ 255 - 255
Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.list.js

@@ -1,256 +1,256 @@
-var ActionsBuilder;
-(function (ActionsBuilder) {
-    var ListElement = (function () {
-        function ListElement() {
-            this.rect = null;
-            this.text = null;
-            this.name = "";
-            this.type = ActionsBuilder.Type.TRIGGER;
-            this.element = null;
-        }
-        return ListElement;
-    })();
-    ActionsBuilder.ListElement = ListElement;
-    var List = (function () {
-        /**
-        * Constructor
-        */
-        function List(viewer) {
-            var _this = this;
-            this._listElements = new Array();
-            // Get HTML elements
-            this.listElement = document.getElementById("ListsElementID");
-            this.triggersElement = document.getElementById("TriggersListID");
-            this.actionsElement = document.getElementById("ActionsListID");
-            this.flowControlsElement = document.getElementById("FlowActionsListID");
-            this._parentContainer = document.getElementById("ParentContainerID");
-            // Configure this
-            this._viewer = viewer;
-            // Create elements (lists)
-            this.triggersList = Raphael("TriggersListID", (25 * screen.width) / 100, 400);
-            this.actionsList = Raphael("ActionsListID", (25 * screen.width) / 100, 400);
-            this.flowControlsList = Raphael("FlowActionsListID", (25 * screen.width) / 100, 400);
-            // Manage events
-            window.addEventListener("resize", function (event) {
-                _this.onResize(event);
-            });
-        }
-        Object.defineProperty(List, "ELEMENT_HEIGHT", {
-            get: function () {
-                return 25;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        /**
-        * Resize event that resizes the list element dynamically
-        * @param event: the resize event
-        */
-        List.prototype.onResize = function (event) {
-            var tools = document.getElementById("ToolsButtonsID");
-            this.listElement.style.height = window.innerHeight - tools.getBoundingClientRect().height - 25 + "px";
-            var listElementWidth = this.listElement.getBoundingClientRect().width;
-            for (var i = 0; i < this._listElements.length; i++) {
-                var rect = this._listElements[i].rect;
-                rect.attr("width", listElementWidth - 40);
-            }
-            this.triggersList.setSize(listElementWidth, this.triggersList.height);
-            this.actionsList.setSize(listElementWidth, this.triggersList.height);
-            this.flowControlsList.setSize(listElementWidth, this.triggersList.height);
-        };
-        List.prototype.createListsElements = function () {
-            var excludedTriggers = [6, 9, 10];
-            var yPosition = 10;
-            var textColor = Raphael.rgb(61, 72, 76);
-            var whiteColor = Raphael.rgb(255, 255, 255);
-            var configureTitle = function (listElement, rectColor) {
-                listElement.text.attr("x", 15);
-                listElement.rect.attr("fill", rectColor);
-                listElement.text.attr("font-family", "Sinkin Sans Medium");
-                listElement.text.attr("font-size", "11");
-            };
-            // Create triggers
-            var triggers = this._createListElement(this.triggersList, yPosition, "TRIGGERS", ActionsBuilder.Type.TRIGGER, whiteColor, false);
-            yPosition += List.ELEMENT_HEIGHT;
-            configureTitle(triggers, Raphael.rgb(41, 129, 255));
-            for (var i = 0; i < ActionsBuilder.Elements.TRIGGERS.length; i++) {
-                var element = ActionsBuilder.Elements.TRIGGERS[i];
-                if (this._viewer.root.type === ActionsBuilder.Type.OBJECT && excludedTriggers.indexOf(i) !== -1) {
-                    continue;
-                }
-                else if (this._viewer.root.type === ActionsBuilder.Type.SCENE && excludedTriggers.indexOf(i) === -1) {
-                    continue;
-                }
-                var trigger = this._createListElement(this.triggersList, yPosition, element.text, ActionsBuilder.Type.TRIGGER, textColor, true, element);
-                trigger.rect.attr("fill", Raphael.rgb(133, 154, 185));
-                yPosition += List.ELEMENT_HEIGHT;
-            }
-            yPosition += List.ELEMENT_HEIGHT;
-            this.triggersElement.style.height = this.triggersList.canvas.style.height = yPosition + "px";
-            this._createCollapseAnimation(this.triggersList, this.triggersElement, triggers, yPosition);
-            // Create actions
-            yPosition = 10;
-            var actions = this._createListElement(this.actionsList, yPosition, "ACTIONS", ActionsBuilder.Type.ACTION, textColor, false);
-            yPosition += List.ELEMENT_HEIGHT;
-            configureTitle(actions, Raphael.rgb(255, 220, 42));
-            for (var i = 0; i < ActionsBuilder.Elements.ACTIONS.length; i++) {
-                var element = ActionsBuilder.Elements.ACTIONS[i];
-                var action = this._createListElement(this.actionsList, yPosition, element.text, ActionsBuilder.Type.ACTION, textColor, true, element);
-                action.rect.attr("fill", Raphael.rgb(182, 185, 132));
-                yPosition += List.ELEMENT_HEIGHT;
-            }
-            yPosition += List.ELEMENT_HEIGHT;
-            this.actionsElement.style.height = this.actionsList.canvas.style.height = yPosition + "px";
-            this._createCollapseAnimation(this.actionsList, this.actionsElement, actions, yPosition);
-            // Create flow controls
-            yPosition = 10;
-            var flowControls = this._createListElement(this.flowControlsList, yPosition, "FLOW CONTROLS", ActionsBuilder.Type.FLOW_CONTROL, whiteColor, false);
-            yPosition += List.ELEMENT_HEIGHT;
-            configureTitle(flowControls, Raphael.rgb(255, 41, 53));
-            for (var i = 0; i < ActionsBuilder.Elements.FLOW_CONTROLS.length - 1; i++) {
-                var element = ActionsBuilder.Elements.FLOW_CONTROLS[i];
-                var flowControl = this._createListElement(this.flowControlsList, yPosition, element.text, ActionsBuilder.Type.FLOW_CONTROL, textColor, true, element);
-                flowControl.rect.attr("fill", Raphael.rgb(185, 132, 140));
-                yPosition += List.ELEMENT_HEIGHT;
-            }
-            yPosition += List.ELEMENT_HEIGHT;
-            this.flowControlsElement.style.height = this.flowControlsList.canvas.style.height = yPosition + "px";
-            this._createCollapseAnimation(this.flowControlsList, this.flowControlsElement, flowControls, yPosition);
-        };
-        /**
-        * Clears the list of elements and removes the elements
-        */
-        List.prototype.clearLists = function () {
-            for (var i = 0; i < this._listElements.length; i++) {
-                this._removeListElement(this._listElements[i]);
-            }
-            this._listElements.splice(0, this._listElements.length - 1);
-        };
-        /**
-        * Sets the color theme of the lists
-        * @param color: the theme color
-        */
-        List.prototype.setColorTheme = function (color) {
-            this.triggersList.canvas.style.backgroundColor = color;
-            this.actionsList.canvas.style.backgroundColor = color;
-            this.flowControlsList.canvas.style.backgroundColor = color;
-        };
-        /**
-        * Creates a list element
-        * @param paper: the Raphael.js paper
-        * @param yPosition: the y position of the element
-        * @param text: the element text
-        * @param type: the element type (trigger, action, flow control)
-        * @param textColor: the text color
-        * @param drag: if the element should be drag'n'dropped
-        */
-        List.prototype._createListElement = function (paper, yPosition, text, type, textColor, drag, element) {
-            var object = new ListElement();
-            object.rect = paper.rect(10, yPosition, 300, List.ELEMENT_HEIGHT);
-            object.text = paper.text(30, yPosition + object.rect.attr("height") / 2, text);
-            object.text.attr("fill", textColor);
-            object.text.attr("text-anchor", "start");
-            object.text.attr("font-size", "12");
-            object.text.attr("text-anchor", "start");
-            object.text.attr("font-family", "Sinkin Sans Light");
-            if (drag) {
-                this._createListElementAnimation(object);
-            }
-            object.type = type;
-            object.element = element;
-            this._listElements.push(object);
-            return object;
-        };
-        /**
-        * Removes a list element
-        * @param element: the element to remove
-        */
-        List.prototype._removeListElement = function (element) {
-            element.rect.remove();
-            element.text.remove();
-        };
-        /*
-        * Creates the collapse animation of a list
-        * @param paper: the list paper
-        * @param htmlElement: the list div container
-        * @param element: the list element to click on
-        * @param expandedHeight: the height when the list is expanded
-        */
-        List.prototype._createCollapseAnimation = function (paper, htmlElement, element, expandedHeight) {
-            var onClick = function (event) {
-                var height = htmlElement.style.height;
-                if (height === expandedHeight + "px") {
-                    htmlElement.style.height = paper.canvas.style.height = 35 + "px";
-                }
-                else {
-                    htmlElement.style.height = paper.canvas.style.height = expandedHeight + "px";
-                }
-            };
-            element.rect.click(onClick);
-        };
-        /*
-        * Creates the animation of a list element
-        * @param element: the list element to animate
-        */
-        List.prototype._createListElementAnimation = function (element) {
-            var _this = this;
-            var onMove = function (dx, dy, x, y) { };
-            var onStart = function (x, y, event) {
-                _this._parentContainer.style.cursor = "copy";
-                element.rect.animate({
-                    x: -10,
-                    opacity: 0.25
-                }, 500, ">");
-                element.text.animate({
-                    x: 10,
-                    opacity: 0.25
-                }, 500, ">");
-            };
-            var onEnd = function (event) {
-                _this._parentContainer.style.cursor = "default";
-                element.rect.animate({
-                    x: 10,
-                    opacity: 1.0
-                }, 500, "<");
-                element.text.animate({
-                    x: 30,
-                    opacity: 1.0
-                }, 500, "<");
-                var dragResult = _this._viewer.traverseGraph(null, _this._viewer.mousex, _this._viewer.mousey, false);
-                if (dragResult.hit) {
-                    if (element.type === ActionsBuilder.Type.TRIGGER && dragResult.action !== _this._viewer.root) {
-                        alert("Triggers can be dragged only on the root node (the mesh)");
-                        return;
-                    }
-                    if (element.type === ActionsBuilder.Type.ACTION && dragResult.action === _this._viewer.root) {
-                        alert("Please add a trigger before.");
-                        return;
-                    }
-                    //if (element.type === Type.FLOW_CONTROL && (dragResult.action === this._viewer.root || (dragResult.action.type === Type.FLOW_CONTROL && dragResult.action.parent.hub === null))) {
-                    if (element.type === ActionsBuilder.Type.FLOW_CONTROL && dragResult.action === _this._viewer.root) {
-                        return;
-                    }
-                    if (element.type === ActionsBuilder.Type.FLOW_CONTROL && dragResult.action.combineArray !== null) {
-                        alert("A condition cannot be handled by a Combine Action.");
-                        return;
-                    }
-                    if ((element.type === ActionsBuilder.Type.FLOW_CONTROL || element.type === ActionsBuilder.Type.ACTION) && dragResult.action.type === ActionsBuilder.Type.TRIGGER && dragResult.action.children.length > 0) {
-                        alert("Triggers can have only one child. Please add another trigger of same type.");
-                        return;
-                    }
-                    if (!(dragResult.action.combineArray !== null) && dragResult.action.children.length > 0 && dragResult.action.type !== ActionsBuilder.Type.TRIGGER && dragResult.action !== _this._viewer.root) {
-                        alert("An action can have only one child.");
-                        return;
-                    }
-                    _this._viewer.addAction(dragResult.action, element.type, element.element);
-                    _this._viewer.update();
-                }
-            };
-            element.rect.drag(onMove, onStart, onEnd);
-            element.text.drag(onMove, onStart, onEnd);
-        };
-        return List;
-    })();
-    ActionsBuilder.List = List;
-})(ActionsBuilder || (ActionsBuilder = {}));
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    var ListElement = (function () {
+        function ListElement() {
+            this.rect = null;
+            this.text = null;
+            this.name = "";
+            this.type = ActionsBuilder.Type.TRIGGER;
+            this.element = null;
+        }
+        return ListElement;
+    }());
+    ActionsBuilder.ListElement = ListElement;
+    var List = (function () {
+        /**
+        * Constructor
+        */
+        function List(viewer) {
+            var _this = this;
+            this._listElements = new Array();
+            // Get HTML elements
+            this.listElement = document.getElementById("ListsElementID");
+            this.triggersElement = document.getElementById("TriggersListID");
+            this.actionsElement = document.getElementById("ActionsListID");
+            this.flowControlsElement = document.getElementById("FlowActionsListID");
+            this._parentContainer = document.getElementById("ParentContainerID");
+            // Configure this
+            this._viewer = viewer;
+            // Create elements (lists)
+            this.triggersList = Raphael("TriggersListID", (25 * screen.width) / 100, 400);
+            this.actionsList = Raphael("ActionsListID", (25 * screen.width) / 100, 400);
+            this.flowControlsList = Raphael("FlowActionsListID", (25 * screen.width) / 100, 400);
+            // Manage events
+            window.addEventListener("resize", function (event) {
+                _this.onResize(event);
+            });
+        }
+        Object.defineProperty(List, "ELEMENT_HEIGHT", {
+            get: function () {
+                return 25;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        /**
+        * Resize event that resizes the list element dynamically
+        * @param event: the resize event
+        */
+        List.prototype.onResize = function (event) {
+            var tools = document.getElementById("ToolsButtonsID");
+            this.listElement.style.height = window.innerHeight - tools.getBoundingClientRect().height - 25 + "px";
+            var listElementWidth = this.listElement.getBoundingClientRect().width;
+            for (var i = 0; i < this._listElements.length; i++) {
+                var rect = this._listElements[i].rect;
+                rect.attr("width", listElementWidth - 40);
+            }
+            this.triggersList.setSize(listElementWidth, this.triggersList.height);
+            this.actionsList.setSize(listElementWidth, this.triggersList.height);
+            this.flowControlsList.setSize(listElementWidth, this.triggersList.height);
+        };
+        List.prototype.createListsElements = function () {
+            var excludedTriggers = [6, 9, 10];
+            var yPosition = 10;
+            var textColor = Raphael.rgb(61, 72, 76);
+            var whiteColor = Raphael.rgb(255, 255, 255);
+            var configureTitle = function (listElement, rectColor) {
+                listElement.text.attr("x", 15);
+                listElement.rect.attr("fill", rectColor);
+                listElement.text.attr("font-family", "Sinkin Sans Medium");
+                listElement.text.attr("font-size", "11");
+            };
+            // Create triggers
+            var triggers = this._createListElement(this.triggersList, yPosition, "TRIGGERS", ActionsBuilder.Type.TRIGGER, whiteColor, false);
+            yPosition += List.ELEMENT_HEIGHT;
+            configureTitle(triggers, Raphael.rgb(41, 129, 255));
+            for (var i = 0; i < ActionsBuilder.Elements.TRIGGERS.length; i++) {
+                var element = ActionsBuilder.Elements.TRIGGERS[i];
+                if (this._viewer.root.type === ActionsBuilder.Type.OBJECT && excludedTriggers.indexOf(i) !== -1) {
+                    continue;
+                }
+                else if (this._viewer.root.type === ActionsBuilder.Type.SCENE && excludedTriggers.indexOf(i) === -1) {
+                    continue;
+                }
+                var trigger = this._createListElement(this.triggersList, yPosition, element.text, ActionsBuilder.Type.TRIGGER, textColor, true, element);
+                trigger.rect.attr("fill", Raphael.rgb(133, 154, 185));
+                yPosition += List.ELEMENT_HEIGHT;
+            }
+            yPosition += List.ELEMENT_HEIGHT;
+            this.triggersElement.style.height = this.triggersList.canvas.style.height = yPosition + "px";
+            this._createCollapseAnimation(this.triggersList, this.triggersElement, triggers, yPosition);
+            // Create actions
+            yPosition = 10;
+            var actions = this._createListElement(this.actionsList, yPosition, "ACTIONS", ActionsBuilder.Type.ACTION, textColor, false);
+            yPosition += List.ELEMENT_HEIGHT;
+            configureTitle(actions, Raphael.rgb(255, 220, 42));
+            for (var i = 0; i < ActionsBuilder.Elements.ACTIONS.length; i++) {
+                var element = ActionsBuilder.Elements.ACTIONS[i];
+                var action = this._createListElement(this.actionsList, yPosition, element.text, ActionsBuilder.Type.ACTION, textColor, true, element);
+                action.rect.attr("fill", Raphael.rgb(182, 185, 132));
+                yPosition += List.ELEMENT_HEIGHT;
+            }
+            yPosition += List.ELEMENT_HEIGHT;
+            this.actionsElement.style.height = this.actionsList.canvas.style.height = yPosition + "px";
+            this._createCollapseAnimation(this.actionsList, this.actionsElement, actions, yPosition);
+            // Create flow controls
+            yPosition = 10;
+            var flowControls = this._createListElement(this.flowControlsList, yPosition, "FLOW CONTROLS", ActionsBuilder.Type.FLOW_CONTROL, whiteColor, false);
+            yPosition += List.ELEMENT_HEIGHT;
+            configureTitle(flowControls, Raphael.rgb(255, 41, 53));
+            for (var i = 0; i < ActionsBuilder.Elements.FLOW_CONTROLS.length - 1; i++) {
+                var element = ActionsBuilder.Elements.FLOW_CONTROLS[i];
+                var flowControl = this._createListElement(this.flowControlsList, yPosition, element.text, ActionsBuilder.Type.FLOW_CONTROL, textColor, true, element);
+                flowControl.rect.attr("fill", Raphael.rgb(185, 132, 140));
+                yPosition += List.ELEMENT_HEIGHT;
+            }
+            yPosition += List.ELEMENT_HEIGHT;
+            this.flowControlsElement.style.height = this.flowControlsList.canvas.style.height = yPosition + "px";
+            this._createCollapseAnimation(this.flowControlsList, this.flowControlsElement, flowControls, yPosition);
+        };
+        /**
+        * Clears the list of elements and removes the elements
+        */
+        List.prototype.clearLists = function () {
+            for (var i = 0; i < this._listElements.length; i++) {
+                this._removeListElement(this._listElements[i]);
+            }
+            this._listElements.splice(0, this._listElements.length - 1);
+        };
+        /**
+        * Sets the color theme of the lists
+        * @param color: the theme color
+        */
+        List.prototype.setColorTheme = function (color) {
+            this.triggersList.canvas.style.backgroundColor = color;
+            this.actionsList.canvas.style.backgroundColor = color;
+            this.flowControlsList.canvas.style.backgroundColor = color;
+        };
+        /**
+        * Creates a list element
+        * @param paper: the Raphael.js paper
+        * @param yPosition: the y position of the element
+        * @param text: the element text
+        * @param type: the element type (trigger, action, flow control)
+        * @param textColor: the text color
+        * @param drag: if the element should be drag'n'dropped
+        */
+        List.prototype._createListElement = function (paper, yPosition, text, type, textColor, drag, element) {
+            var object = new ListElement();
+            object.rect = paper.rect(10, yPosition, 300, List.ELEMENT_HEIGHT);
+            object.text = paper.text(30, yPosition + object.rect.attr("height") / 2, text);
+            object.text.attr("fill", textColor);
+            object.text.attr("text-anchor", "start");
+            object.text.attr("font-size", "12");
+            object.text.attr("text-anchor", "start");
+            object.text.attr("font-family", "Sinkin Sans Light");
+            if (drag) {
+                this._createListElementAnimation(object);
+            }
+            object.type = type;
+            object.element = element;
+            this._listElements.push(object);
+            return object;
+        };
+        /**
+        * Removes a list element
+        * @param element: the element to remove
+        */
+        List.prototype._removeListElement = function (element) {
+            element.rect.remove();
+            element.text.remove();
+        };
+        /*
+        * Creates the collapse animation of a list
+        * @param paper: the list paper
+        * @param htmlElement: the list div container
+        * @param element: the list element to click on
+        * @param expandedHeight: the height when the list is expanded
+        */
+        List.prototype._createCollapseAnimation = function (paper, htmlElement, element, expandedHeight) {
+            var onClick = function (event) {
+                var height = htmlElement.style.height;
+                if (height === expandedHeight + "px") {
+                    htmlElement.style.height = paper.canvas.style.height = 35 + "px";
+                }
+                else {
+                    htmlElement.style.height = paper.canvas.style.height = expandedHeight + "px";
+                }
+            };
+            element.rect.click(onClick);
+        };
+        /*
+        * Creates the animation of a list element
+        * @param element: the list element to animate
+        */
+        List.prototype._createListElementAnimation = function (element) {
+            var _this = this;
+            var onMove = function (dx, dy, x, y) { };
+            var onStart = function (x, y, event) {
+                _this._parentContainer.style.cursor = "copy";
+                element.rect.animate({
+                    x: -10,
+                    opacity: 0.25
+                }, 500, ">");
+                element.text.animate({
+                    x: 10,
+                    opacity: 0.25
+                }, 500, ">");
+            };
+            var onEnd = function (event) {
+                _this._parentContainer.style.cursor = "default";
+                element.rect.animate({
+                    x: 10,
+                    opacity: 1.0
+                }, 500, "<");
+                element.text.animate({
+                    x: 30,
+                    opacity: 1.0
+                }, 500, "<");
+                var dragResult = _this._viewer.traverseGraph(null, _this._viewer.mousex, _this._viewer.mousey, false);
+                if (dragResult.hit) {
+                    if (element.type === ActionsBuilder.Type.TRIGGER && dragResult.action !== _this._viewer.root) {
+                        alert("Triggers can be dragged only on the root node (the mesh)");
+                        return;
+                    }
+                    if (element.type === ActionsBuilder.Type.ACTION && dragResult.action === _this._viewer.root) {
+                        alert("Please add a trigger before.");
+                        return;
+                    }
+                    //if (element.type === Type.FLOW_CONTROL && (dragResult.action === this._viewer.root || (dragResult.action.type === Type.FLOW_CONTROL && dragResult.action.parent.hub === null))) {
+                    if (element.type === ActionsBuilder.Type.FLOW_CONTROL && dragResult.action === _this._viewer.root) {
+                        return;
+                    }
+                    if (element.type === ActionsBuilder.Type.FLOW_CONTROL && dragResult.action.combineArray !== null) {
+                        alert("A condition cannot be handled by a Combine Action.");
+                        return;
+                    }
+                    if ((element.type === ActionsBuilder.Type.FLOW_CONTROL || element.type === ActionsBuilder.Type.ACTION) && dragResult.action.type === ActionsBuilder.Type.TRIGGER && dragResult.action.children.length > 0) {
+                        alert("Triggers can have only one child. Please add another trigger of same type.");
+                        return;
+                    }
+                    if (!(dragResult.action.combineArray !== null) && dragResult.action.children.length > 0 && dragResult.action.type !== ActionsBuilder.Type.TRIGGER && dragResult.action !== _this._viewer.root) {
+                        alert("An action can have only one child.");
+                        return;
+                    }
+                    _this._viewer.addAction(dragResult.action, element.type, element.element);
+                    _this._viewer.update();
+                }
+            };
+            element.rect.drag(onMove, onStart, onEnd);
+            element.text.drag(onMove, onStart, onEnd);
+        };
+        return List;
+    }());
+    ActionsBuilder.List = List;
+})(ActionsBuilder || (ActionsBuilder = {}));
 //# sourceMappingURL=actionsbuilder.list.js.map

+ 107 - 101
Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.main.js

@@ -1,102 +1,108 @@
-/*
-Global functions called by the plugins (3ds Max, etc.)
-*/
-// Elements
-var list = null;
-var viewer = null;
-var actionsBuilderJsonInput = document.getElementById("ActionsBuilderJSON");
-this.createJSON = function () {
-    var structure = viewer.utils.createJSON(viewer.root);
-    var asText = JSON.stringify(structure);
-    actionsBuilderJsonInput.value = asText;
-    console.log(asText);
-};
-this.loadFromJSON = function () {
-    var json = actionsBuilderJsonInput.value;
-    if (json !== "") {
-        var structure = JSON.parse(json);
-        viewer.utils.loadFromJSON(structure, null);
-    }
-};
-this.updateObjectName = function () {
-    var element = document.getElementById("ActionsBuilderObjectName");
-    var name = element.value;
-    viewer.objectName = name;
-    if (viewer.root.type === ActionsBuilder.Type.OBJECT) {
-        name += " - Mesh";
-    }
-    else {
-        name += " - Scene";
-    }
-    viewer.root.node.text.attr("text", name);
-};
-this.resetList = function () {
-    list.clearLists();
-    list.createListsElements();
-};
-this.setMeshesNames = function () {
-    var args = [];
-    for (var _i = 0; _i < arguments.length; _i++) {
-        args[_i - 0] = arguments[_i];
-    }
-    for (var i = 0; i < args.length; i++) {
-        ActionsBuilder.SceneElements.MESHES.push(args[i]);
-    }
-};
-this.setLightsNames = function () {
-    var args = [];
-    for (var _i = 0; _i < arguments.length; _i++) {
-        args[_i - 0] = arguments[_i];
-    }
-    for (var i = 0; i < args.length; i++) {
-        ActionsBuilder.SceneElements.LIGHTS.push(args[i]);
-    }
-};
-this.setCamerasNames = function () {
-    var args = [];
-    for (var _i = 0; _i < arguments.length; _i++) {
-        args[_i - 0] = arguments[_i];
-    }
-    for (var i = 0; i < args.length; i++) {
-        ActionsBuilder.SceneElements.CAMERAS.push(args[i]);
-    }
-};
-this.setSoundsNames = function () {
-    var args = [];
-    for (var _i = 0; _i < arguments.length; _i++) {
-        args[_i - 0] = arguments[_i];
-    }
-    for (var i = 0; i < args.length; i++) {
-        var sound = args[i];
-        if (sound !== "" && ActionsBuilder.SceneElements.SOUNDS.indexOf(sound) === -1) {
-            ActionsBuilder.SceneElements.SOUNDS.push(args[i]);
-        }
-    }
-};
-this.hideButtons = function () {
-    // Empty
-};
-this.setIsObject = function () {
-    viewer.root.type = ActionsBuilder.Type.OBJECT;
-};
-this.setIsScene = function () {
-    viewer.root.type = ActionsBuilder.Type.SCENE;
-};
-this.run = function () {
-    // Configure viewer
-    viewer = new ActionsBuilder.Viewer(ActionsBuilder.Type.OBJECT);
-    viewer.setColorTheme("-ms-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
-    viewer.setColorTheme("linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
-    viewer.setColorTheme("-webkit-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
-    viewer.setColorTheme("-o-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
-    viewer.onResize();
-    viewer.update();
-    // Configure list
-    list = new ActionsBuilder.List(viewer);
-    list.setColorTheme("rgb(64, 64, 64)");
-    list.createListsElements();
-    list.onResize();
-    // 3ds Max fix
-    viewer.onResize();
-};
+/*
+Global functions called by the plugins (3ds Max, etc.)
+*/
+// Elements
+var list = null;
+var viewer = null;
+var actionsBuilderJsonInput = document.getElementById("ActionsBuilderJSON");
+this.getList = function () {
+    return list;
+};
+this.getViewer = function () {
+    return viewer;
+};
+this.createJSON = function () {
+    var structure = viewer.utils.createJSON(viewer.root);
+    var asText = JSON.stringify(structure);
+    actionsBuilderJsonInput.value = asText;
+    console.log(asText);
+};
+this.loadFromJSON = function () {
+    var json = actionsBuilderJsonInput.value;
+    if (json !== "") {
+        var structure = JSON.parse(json);
+        viewer.utils.loadFromJSON(structure, null);
+    }
+};
+this.updateObjectName = function () {
+    var element = document.getElementById("ActionsBuilderObjectName");
+    var name = element.value;
+    viewer.objectName = name;
+    if (viewer.root.type === ActionsBuilder.Type.OBJECT) {
+        name += " - Mesh";
+    }
+    else {
+        name += " - Scene";
+    }
+    viewer.root.node.text.attr("text", name);
+};
+this.resetList = function () {
+    list.clearLists();
+    list.createListsElements();
+};
+this.setMeshesNames = function () {
+    var args = [];
+    for (var _i = 0; _i < arguments.length; _i++) {
+        args[_i] = arguments[_i];
+    }
+    for (var i = 0; i < args.length; i++) {
+        ActionsBuilder.SceneElements.MESHES.push(args[i]);
+    }
+};
+this.setLightsNames = function () {
+    var args = [];
+    for (var _i = 0; _i < arguments.length; _i++) {
+        args[_i] = arguments[_i];
+    }
+    for (var i = 0; i < args.length; i++) {
+        ActionsBuilder.SceneElements.LIGHTS.push(args[i]);
+    }
+};
+this.setCamerasNames = function () {
+    var args = [];
+    for (var _i = 0; _i < arguments.length; _i++) {
+        args[_i] = arguments[_i];
+    }
+    for (var i = 0; i < args.length; i++) {
+        ActionsBuilder.SceneElements.CAMERAS.push(args[i]);
+    }
+};
+this.setSoundsNames = function () {
+    var args = [];
+    for (var _i = 0; _i < arguments.length; _i++) {
+        args[_i] = arguments[_i];
+    }
+    for (var i = 0; i < args.length; i++) {
+        var sound = args[i];
+        if (sound !== "" && ActionsBuilder.SceneElements.SOUNDS.indexOf(sound) === -1) {
+            ActionsBuilder.SceneElements.SOUNDS.push(args[i]);
+        }
+    }
+};
+this.hideButtons = function () {
+    // Empty
+};
+this.setIsObject = function () {
+    viewer.root.type = ActionsBuilder.Type.OBJECT;
+};
+this.setIsScene = function () {
+    viewer.root.type = ActionsBuilder.Type.SCENE;
+};
+this.run = function () {
+    // Configure viewer
+    viewer = new ActionsBuilder.Viewer(ActionsBuilder.Type.OBJECT);
+    viewer.setColorTheme("-ms-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
+    viewer.setColorTheme("linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
+    viewer.setColorTheme("-webkit-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
+    viewer.setColorTheme("-o-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
+    viewer.onResize();
+    viewer.update();
+    // Configure list
+    list = new ActionsBuilder.List(viewer);
+    list.setColorTheme("rgb(64, 64, 64)");
+    list.createListsElements();
+    list.onResize();
+    // 3ds Max fix
+    viewer.onResize();
+};
 //# sourceMappingURL=actionsbuilder.main.js.map

+ 111 - 110
Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.max.js

@@ -17,7 +17,7 @@ var ActionsBuilder;
             return this.rect.isPointInside(x, y) || this.text.isPointInside(x, y);
         };
         return Node;
-    })();
+    }());
     ActionsBuilder.Node = Node;
     var Action = (function () {
         /**
@@ -81,7 +81,7 @@ var ActionsBuilder;
             this.children = new Array();
         };
         return Action;
-    })();
+    }());
     ActionsBuilder.Action = Action;
 })(ActionsBuilder || (ActionsBuilder = {}));
 var ActionsBuilder;
@@ -199,7 +199,7 @@ var ActionsBuilder;
             element.addEventListener("contextmenu", onRightClick);
         };
         return ContextMenu;
-    })();
+    }());
     ActionsBuilder.ContextMenu = ContextMenu;
 })(ActionsBuilder || (ActionsBuilder = {}));
 var ActionsBuilder;
@@ -213,7 +213,7 @@ var ActionsBuilder;
             this.element = null;
         }
         return ListElement;
-    })();
+    }());
     ActionsBuilder.ListElement = ListElement;
     var List = (function () {
         /**
@@ -454,7 +454,7 @@ var ActionsBuilder;
             element.text.drag(onMove, onStart, onEnd);
         };
         return List;
-    })();
+    }());
     ActionsBuilder.List = List;
 })(ActionsBuilder || (ActionsBuilder = {}));
 /*
@@ -464,6 +464,12 @@ Global functions called by the plugins (3ds Max, etc.)
 var list = null;
 var viewer = null;
 var actionsBuilderJsonInput = document.getElementById("ActionsBuilderJSON");
+this.getList = function () {
+    return list;
+};
+this.getViewer = function () {
+    return viewer;
+};
 this.createJSON = function () {
     var structure = viewer.utils.createJSON(viewer.root);
     var asText = JSON.stringify(structure);
@@ -496,7 +502,7 @@ this.resetList = function () {
 this.setMeshesNames = function () {
     var args = [];
     for (var _i = 0; _i < arguments.length; _i++) {
-        args[_i - 0] = arguments[_i];
+        args[_i] = arguments[_i];
     }
     for (var i = 0; i < args.length; i++) {
         ActionsBuilder.SceneElements.MESHES.push(args[i]);
@@ -505,7 +511,7 @@ this.setMeshesNames = function () {
 this.setLightsNames = function () {
     var args = [];
     for (var _i = 0; _i < arguments.length; _i++) {
-        args[_i - 0] = arguments[_i];
+        args[_i] = arguments[_i];
     }
     for (var i = 0; i < args.length; i++) {
         ActionsBuilder.SceneElements.LIGHTS.push(args[i]);
@@ -514,7 +520,7 @@ this.setLightsNames = function () {
 this.setCamerasNames = function () {
     var args = [];
     for (var _i = 0; _i < arguments.length; _i++) {
-        args[_i - 0] = arguments[_i];
+        args[_i] = arguments[_i];
     }
     for (var i = 0; i < args.length; i++) {
         ActionsBuilder.SceneElements.CAMERAS.push(args[i]);
@@ -523,7 +529,7 @@ this.setCamerasNames = function () {
 this.setSoundsNames = function () {
     var args = [];
     for (var _i = 0; _i < arguments.length; _i++) {
-        args[_i - 0] = arguments[_i];
+        args[_i] = arguments[_i];
     }
     for (var i = 0; i < args.length; i++) {
         var sound = args[i];
@@ -627,20 +633,30 @@ var ActionsBuilder;
                 parameterName.className = "ParametersElementTitleClass";
                 this.parametersContainer.appendChild(parameterName);
                 if (properties[i].text === "parameter" || properties[i].text === "target" || properties[i].text === "parent") {
-                    // Create target select element
-                    targetParameterSelect = document.createElement("select");
-                    targetParameterSelect.className = "ParametersElementSelectClass";
-                    this.parametersContainer.appendChild(targetParameterSelect);
-                    // Create target name select element
-                    targetParameterNameSelect = document.createElement("select");
-                    targetParameterNameSelect.className = "ParametersElementSelectClass";
-                    this.parametersContainer.appendChild(targetParameterNameSelect);
-                    // Events and configure
-                    (this._parameterTargetChanged(targetParameterSelect, targetParameterNameSelect, propertyPathSelect, propertyPathOptionalSelect, i))(null);
-                    targetParameterSelect.value = propertiesResults[i].targetType;
-                    targetParameterNameSelect.value = propertiesResults[i].value;
-                    targetParameterSelect.onchange = this._parameterTargetChanged(targetParameterSelect, targetParameterNameSelect, propertyPathSelect, propertyPathOptionalSelect, i);
-                    targetParameterNameSelect.onchange = this._parameterTargetNameChanged(targetParameterSelect, targetParameterNameSelect, i);
+                    if (properties[i].targetType === null) {
+                        var parameterInput = document.createElement("input");
+                        parameterInput.value = propertiesResults[i].value;
+                        parameterInput.className = "ParametersElementInputClass";
+                        this.parametersContainer.appendChild(parameterInput);
+                        // Configure event
+                        parameterInput.onkeyup = this._propertyInputChanged(parameterInput, i);
+                    }
+                    else {
+                        // Create target select element
+                        targetParameterSelect = document.createElement("select");
+                        targetParameterSelect.className = "ParametersElementSelectClass";
+                        this.parametersContainer.appendChild(targetParameterSelect);
+                        // Create target name select element
+                        targetParameterNameSelect = document.createElement("select");
+                        targetParameterNameSelect.className = "ParametersElementSelectClass";
+                        this.parametersContainer.appendChild(targetParameterNameSelect);
+                        // Events and configure
+                        (this._parameterTargetChanged(targetParameterSelect, targetParameterNameSelect, propertyPathSelect, propertyPathOptionalSelect, i))(null);
+                        targetParameterSelect.value = propertiesResults[i].targetType;
+                        targetParameterNameSelect.value = propertiesResults[i].value;
+                        targetParameterSelect.onchange = this._parameterTargetChanged(targetParameterSelect, targetParameterNameSelect, propertyPathSelect, propertyPathOptionalSelect, i);
+                        targetParameterNameSelect.onchange = this._parameterTargetNameChanged(targetParameterSelect, targetParameterNameSelect, i);
+                    }
                 }
                 else if (properties[i].text === "propertyPath") {
                     propertyPathIndice = i;
@@ -670,7 +686,7 @@ var ActionsBuilder;
                         }
                         this._fillAdditionalPropertyPath(targetParameterSelect, propertyPathSelect, propertyPathOptionalSelect);
                         propertyPathOptionalSelect.value = property[property.length - 1];
-                        if (propertyPathOptionalSelect.options.length === 0 || propertyPathOptionalSelect.options[0].text === "") {
+                        if (propertyPathOptionalSelect.options.length === 0 || propertyPathOptionalSelect.options[0].textContent === "") {
                             this._viewer.utils.setElementVisible(propertyPathOptionalSelect, false);
                         }
                     }
@@ -757,7 +773,7 @@ var ActionsBuilder;
                     for (var i = 0; i < values.length; i++) {
                         var option = document.createElement("option");
                         option.value = option.text = values[i];
-                        booleanSelect.options.add(option);
+                        booleanSelect.add(option);
                     }
                 }
                 else {
@@ -777,7 +793,7 @@ var ActionsBuilder;
                     for (var i = 0; i < ActionsBuilder.SceneElements.SOUNDS.length; i++) {
                         var option = document.createElement("option");
                         option.value = option.text = ActionsBuilder.SceneElements.SOUNDS[i];
-                        soundSelect.options.add(option);
+                        soundSelect.add(option);
                     }
                     _this._sortList(soundSelect);
                 }
@@ -798,7 +814,8 @@ var ActionsBuilder;
                     for (var i = 0; i < ActionsBuilder.SceneElements.OPERATORS.length; i++) {
                         var option = document.createElement("option");
                         option.value = option.text = ActionsBuilder.SceneElements.OPERATORS[i];
-                        conditionOperatorSelect.options.add(option);
+                        //conditionOperatorSelect.options.add(option);
+                        conditionOperatorSelect.add(option);
                     }
                 }
                 else {
@@ -834,7 +851,7 @@ var ActionsBuilder;
                         for (var i = 0; i < properties.length; i++) {
                             var option = document.createElement("option");
                             option.value = option.text = properties[i];
-                            propertyPathSelect.options.add(option);
+                            propertyPathSelect.add(option);
                         }
                     }
                 }
@@ -892,11 +909,11 @@ var ActionsBuilder;
                 if (index !== -1) {
                     var option = document.createElement("option");
                     option.value = option.text = thing;
-                    additionalPropertyPathSelect.options.add(option);
+                    additionalPropertyPathSelect.add(option);
                     emptyOption.text += thing + ", ";
                 }
             }
-            if (additionalPropertyPathSelect.options.length === 0 || additionalPropertyPathSelect.options[0].text === "") {
+            if (additionalPropertyPathSelect.options.length === 0 || additionalPropertyPathSelect.options[0].textContent === "") {
                 this._viewer.utils.setElementVisible(additionalPropertyPathSelect, false);
             }
             else {
@@ -945,7 +962,7 @@ var ActionsBuilder;
                         var option = document.createElement("option");
                         option.text = options[i].text;
                         option.value = options[i].targetType;
-                        targetParameterSelect.options.add(option);
+                        targetParameterSelect.add(option);
                     }
                     targetParameterSelect.value = _this._action.propertiesResults[indice].targetType;
                 }
@@ -969,7 +986,7 @@ var ActionsBuilder;
                     for (var i = 0; i < targetParameterProperties.length; i++) {
                         var option = document.createElement("option");
                         option.text = option.value = targetParameterProperties[i];
-                        targetParameterNameSelect.options.add(option);
+                        targetParameterNameSelect.add(option);
                     }
                 }
                 targetParameterNameSelect.value = _this._action.propertiesResults[indice].value;
@@ -1101,11 +1118,11 @@ var ActionsBuilder;
                 return a.innerHTML.localeCompare(b.innerHTML);
             });
             for (var i = 0; i < options.length; i++) {
-                element.options.add(options[i]);
+                element.add(options[i]);
             }
         };
         return Parameters;
-    })();
+    }());
     ActionsBuilder.Parameters = Parameters;
 })(ActionsBuilder || (ActionsBuilder = {}));
 var ActionsBuilder;
@@ -1190,7 +1207,7 @@ var ActionsBuilder;
             this.saveActionGraphElement.style.display = draw ? "block" : "none";
         };
         return Toolbar;
-    })();
+    }());
     ActionsBuilder.Toolbar = Toolbar;
 })(ActionsBuilder || (ActionsBuilder = {}));
 var ActionsBuilder;
@@ -1236,13 +1253,13 @@ var ActionsBuilder;
             enumerable: true,
             configurable: true
         });
-        Type._TRIGGER = 0;
-        Type._ACTION = 1;
-        Type._FLOW_CONTROL = 2;
-        Type._OBJECT = 3;
-        Type._SCENE = 4;
         return Type;
-    })();
+    }());
+    Type._TRIGGER = 0;
+    Type._ACTION = 1;
+    Type._FLOW_CONTROL = 2;
+    Type._OBJECT = 3;
+    Type._SCENE = 4;
     ActionsBuilder.Type = Type;
     /*
     * Defines the BABYLON.JS elements
@@ -1378,38 +1395,38 @@ var ActionsBuilder;
             }
             return false;
         };
-        /*
-        * BabylonJS objects
-        */
-        SceneElements._ENGINE = new BABYLON.Engine(document.getElementById("RenderCanvasID"));
-        SceneElements._SCENE = new BABYLON.Scene(SceneElements.ENGINE);
-        SceneElements._MESH = new BABYLON.Mesh("mesh", SceneElements._SCENE);
-        SceneElements._LIGHT = new BABYLON.Light("light", SceneElements._SCENE);
-        SceneElements._CAMERA = new BABYLON.Camera("camera", BABYLON.Vector3.Zero(), SceneElements._SCENE);
-        /*
-        * Objects names
-        */
-        SceneElements._MESHES = new Array();
-        SceneElements._LIGHTS = new Array();
-        SceneElements._CAMERAS = new Array();
-        SceneElements._SOUNDS = new Array();
-        /*
-        * Properties
-        */
-        SceneElements._MESH_PROPERTIES = new Array();
-        SceneElements._LIGHT_PROPERTIES = new Array();
-        SceneElements._CAMERA_PROPERTIES = new Array();
-        SceneElements._SCENE_PROPERTIES = new Array();
-        /*
-        * Types
-        */
-        SceneElements._TYPES = new Array();
-        /*
-        * Operators
-        */
-        SceneElements._OPERATORS = new Array();
         return SceneElements;
-    })();
+    }());
+    /*
+    * BabylonJS objects
+    */
+    SceneElements._ENGINE = new BABYLON.Engine(document.getElementById("RenderCanvasID"));
+    SceneElements._SCENE = new BABYLON.Scene(SceneElements.ENGINE);
+    SceneElements._MESH = new BABYLON.Mesh("mesh", SceneElements._SCENE);
+    SceneElements._LIGHT = new BABYLON.Light("light", SceneElements._SCENE);
+    SceneElements._CAMERA = new BABYLON.Camera("camera", BABYLON.Vector3.Zero(), SceneElements._SCENE);
+    /*
+    * Objects names
+    */
+    SceneElements._MESHES = new Array();
+    SceneElements._LIGHTS = new Array();
+    SceneElements._CAMERAS = new Array();
+    SceneElements._SOUNDS = new Array();
+    /*
+    * Properties
+    */
+    SceneElements._MESH_PROPERTIES = new Array();
+    SceneElements._LIGHT_PROPERTIES = new Array();
+    SceneElements._CAMERA_PROPERTIES = new Array();
+    SceneElements._SCENE_PROPERTIES = new Array();
+    /*
+    * Types
+    */
+    SceneElements._TYPES = new Array();
+    /*
+    * Operators
+    */
+    SceneElements._OPERATORS = new Array();
     ActionsBuilder.SceneElements = SceneElements;
     // Functions
     var specialTypes = [
@@ -1508,11 +1525,11 @@ var ActionsBuilder;
             }
             return null;
         };
-        Elements._TRIGGERS = new Array();
-        Elements._ACTIONS = new Array();
-        Elements._FLOW_CONTROLS = new Array();
         return Elements;
-    })();
+    }());
+    Elements._TRIGGERS = new Array();
+    Elements._ACTIONS = new Array();
+    Elements._FLOW_CONTROLS = new Array();
     ActionsBuilder.Elements = Elements;
     // Configure triggers
     Elements.TRIGGERS.push({ name: "OnPickTrigger", text: "pick", properties: [], description: "When the user picks the edited mesh" });
@@ -1524,8 +1541,8 @@ var ActionsBuilder;
     Elements.TRIGGERS.push({ name: "OnEveryFrameTrigger", text: "every frame", properties: [], description: "This trigger is called each frame (only on scene)" });
     Elements.TRIGGERS.push({ name: "OnIntersectionEnterTrigger", text: "intersection enter", properties: [{ targetType: "MeshProperties", text: "parameter", value: "Object name?" }], description: "When the edited mesh intersects the another mesh predefined in the options" });
     Elements.TRIGGERS.push({ name: "OnIntersectionExitTrigger", text: "intersection exit", properties: [{ targetType: "MeshProperties", text: "parameter", value: "Object name?" }], description: "When the edited mesh exits intersection with the another mesh predefined in the options" });
-    Elements.TRIGGERS.push({ name: "OnKeyDownTrigger", text: "key down", properties: [{ targetType: null, text: "parameter:", value: "a" }], description: "When the user pressed a key (enter the key character, example: \"r\")" });
-    Elements.TRIGGERS.push({ name: "OnKeyUpTrigger", text: "key up", properties: [{ targetType: null, text: "parameter:", value: "a" }], description: "When the user unpressed a key (enter the key character, example: \"p\")" });
+    Elements.TRIGGERS.push({ name: "OnKeyDownTrigger", text: "key down", properties: [{ targetType: null, text: "parameter", value: "a" }], description: "When the user pressed a key (enter the key character, example: \"r\")" });
+    Elements.TRIGGERS.push({ name: "OnKeyUpTrigger", text: "key up", properties: [{ targetType: null, text: "parameter", value: "a" }], description: "When the user unpressed a key (enter the key character, example: \"p\")" });
     // Configure actions
     Elements.ACTIONS.push({ name: "SwitchBooleanAction", text: "switch boolean", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }], description: "Switches the boolean value of a given parameter of the target object: true to false, or false to true" });
     Elements.ACTIONS.push({ name: "SetStateAction", text: "set state", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "value", value: "" }], description: "Sets a new state value for the target object (example: \"off\" or \"on\")" });
@@ -1974,7 +1991,7 @@ var ActionsBuilder;
             element.style.display = visible ? "block" : "none";
         };
         return Utils;
-    })();
+    }());
     ActionsBuilder.Utils = Utils;
 })(ActionsBuilder || (ActionsBuilder = {}));
 var ActionsBuilder;
@@ -2114,19 +2131,11 @@ var ActionsBuilder;
                 return Raphael.rgb(96, 122, 14);
             }
             switch (type) {
-                case ActionsBuilder.Type.TRIGGER:
-                    return Raphael.rgb(133, 154, 185);
-                    break;
-                case ActionsBuilder.Type.ACTION:
-                    return Raphael.rgb(182, 185, 132);
-                    break;
-                case ActionsBuilder.Type.FLOW_CONTROL:
-                    return Raphael.rgb(185, 132, 140);
-                    break;
+                case ActionsBuilder.Type.TRIGGER: return Raphael.rgb(133, 154, 185);
+                case ActionsBuilder.Type.ACTION: return Raphael.rgb(182, 185, 132);
+                case ActionsBuilder.Type.FLOW_CONTROL: return Raphael.rgb(185, 132, 140);
                 case ActionsBuilder.Type.OBJECT:
-                case ActionsBuilder.Type.SCENE:
-                    return Raphael.rgb(255, 255, 255);
-                    break;
+                case ActionsBuilder.Type.SCENE: return Raphael.rgb(255, 255, 255);
                 default: break;
             }
             return null;
@@ -2141,19 +2150,11 @@ var ActionsBuilder;
                 return Raphael.rgb(96, 122, 14);
             }
             switch (type) {
-                case ActionsBuilder.Type.TRIGGER:
-                    return Raphael.rgb(41, 129, 255);
-                    break;
-                case ActionsBuilder.Type.ACTION:
-                    return Raphael.rgb(255, 220, 42);
-                    break;
-                case ActionsBuilder.Type.FLOW_CONTROL:
-                    return Raphael.rgb(255, 41, 53);
-                    break;
+                case ActionsBuilder.Type.TRIGGER: return Raphael.rgb(41, 129, 255);
+                case ActionsBuilder.Type.ACTION: return Raphael.rgb(255, 220, 42);
+                case ActionsBuilder.Type.FLOW_CONTROL: return Raphael.rgb(255, 41, 53);
                 case ActionsBuilder.Type.OBJECT:
-                case ActionsBuilder.Type.SCENE:
-                    return Raphael.rgb(255, 255, 255);
-                    break;
+                case ActionsBuilder.Type.SCENE: return Raphael.rgb(255, 255, 255);
                 default: break;
             }
             return null;
@@ -2614,13 +2615,13 @@ var ActionsBuilder;
             node.rect.drag(onMove, onStart, onEnd);
             node.text.drag(onMove, onStart, onEnd);
         };
-        // Statics
-        Viewer._NODE_WIDTH = 150;
-        Viewer._NODE_HEIGHT = 25;
-        Viewer._NODE_MINIMIZE_WIDTH = 50;
-        Viewer._VERTICAL_OFFSET = 70;
-        Viewer._DEFAULT_INFO_MESSAGE = "Select or add a node to customize actions";
         return Viewer;
-    })();
+    }());
+    // Statics
+    Viewer._NODE_WIDTH = 150;
+    Viewer._NODE_HEIGHT = 25;
+    Viewer._NODE_MINIMIZE_WIDTH = 50;
+    Viewer._VERTICAL_OFFSET = 70;
+    Viewer._DEFAULT_INFO_MESSAGE = "Select or add a node to customize actions";
     ActionsBuilder.Viewer = Viewer;
 })(ActionsBuilder || (ActionsBuilder = {}));

文件差異過大導致無法顯示
+ 561 - 550
Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.parameters.js


+ 85 - 85
Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.toolbar.js

@@ -1,86 +1,86 @@
-var ActionsBuilder;
-(function (ActionsBuilder) {
-    var Toolbar = (function () {
-        function Toolbar(viewer) {
-            var _this = this;
-            // Get HTML elements
-            this.toolbarElement = document.getElementById("ToolbarElementID");
-            // Configure this
-            this._viewer = viewer;
-            // Manage events
-            window.addEventListener("resize", function (event) {
-                _this.onResize();
-            });
-            // Bottom toolbar
-            document.getElementById("ViewerDeZoomID").addEventListener("click", function (event) {
-                if (_this._viewer.zoom > 0.1) {
-                    _this._viewer.zoom -= 0.1;
-                }
-                _this._viewer.update();
-            });
-            document.getElementById("ViewerZoomID").addEventListener("click", function (event) {
-                if (_this._viewer.zoom < 1.0) {
-                    _this._viewer.zoom += 0.1;
-                }
-                _this._viewer.update();
-            });
-            document.getElementById("ViewerReconnectAll").addEventListener("click", function (event) {
-                for (var i = 0; i < _this._viewer.root.children.length; i++) {
-                    _this._viewer.selectedNode = _this._viewer.root.children[i];
-                    _this._viewer.utils.onDetachAction(false, true);
-                }
-                _this._viewer.update();
-                _this._viewer.selectedNode = null;
-            });
-            document.getElementById("ViewerDisconnectAll").addEventListener("click", function (event) {
-                for (var i = 0; i < _this._viewer.root.children.length; i++) {
-                    _this._viewer.selectedNode = _this._viewer.root.children[i];
-                    _this._viewer.utils.onDetachAction(true, false);
-                }
-                _this._viewer.update();
-                _this._viewer.selectedNode = null;
-            });
-            document.getElementById("ViewerReduceAll").addEventListener("click", function (event) {
-                for (var i = 0; i < _this._viewer.root.children.length; i++) {
-                    _this._viewer.selectedNode = _this._viewer.root.children[i];
-                    _this._viewer.utils.onReduceAll(false);
-                }
-                _this._viewer.update();
-                _this._viewer.selectedNode = null;
-            });
-            document.getElementById("ViewerExpandAll").addEventListener("click", function (event) {
-                for (var i = 0; i < _this._viewer.root.children.length; i++) {
-                    _this._viewer.selectedNode = _this._viewer.root.children[i];
-                    _this._viewer.utils.onReduceAll(true);
-                }
-                _this._viewer.update();
-                _this._viewer.selectedNode = null;
-            });
-            // Top toolbar
-            this.saveActionGraphElement = document.getElementById("ToolsButtonIDSaveActionGraph");
-            this.drawSaveActionGraphButton(false);
-            document.getElementById("ResetActionGraphID").addEventListener("click", function (event) {
-                if (confirm("Are you sure?")) {
-                    for (var i = 0; i < _this._viewer.root.children.length; i++) {
-                        _this._viewer.selectedNode = _this._viewer.root.children[i];
-                        _this._viewer.utils.onRemoveBranch();
-                    }
-                    _this._viewer.update();
-                    _this._viewer.selectedNode = null;
-                }
-            });
-            document.getElementById("TestActionGraphID").addEventListener("click", function (event) {
-                _this._viewer.utils.onTestGraph();
-            });
-        }
-        Toolbar.prototype.onResize = function () {
-            this.toolbarElement.style.top = this._viewer.viewerElement.clientHeight + 20 + "px";
-        };
-        Toolbar.prototype.drawSaveActionGraphButton = function (draw) {
-            this.saveActionGraphElement.style.display = draw ? "block" : "none";
-        };
-        return Toolbar;
-    })();
-    ActionsBuilder.Toolbar = Toolbar;
-})(ActionsBuilder || (ActionsBuilder = {}));
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    var Toolbar = (function () {
+        function Toolbar(viewer) {
+            var _this = this;
+            // Get HTML elements
+            this.toolbarElement = document.getElementById("ToolbarElementID");
+            // Configure this
+            this._viewer = viewer;
+            // Manage events
+            window.addEventListener("resize", function (event) {
+                _this.onResize();
+            });
+            // Bottom toolbar
+            document.getElementById("ViewerDeZoomID").addEventListener("click", function (event) {
+                if (_this._viewer.zoom > 0.1) {
+                    _this._viewer.zoom -= 0.1;
+                }
+                _this._viewer.update();
+            });
+            document.getElementById("ViewerZoomID").addEventListener("click", function (event) {
+                if (_this._viewer.zoom < 1.0) {
+                    _this._viewer.zoom += 0.1;
+                }
+                _this._viewer.update();
+            });
+            document.getElementById("ViewerReconnectAll").addEventListener("click", function (event) {
+                for (var i = 0; i < _this._viewer.root.children.length; i++) {
+                    _this._viewer.selectedNode = _this._viewer.root.children[i];
+                    _this._viewer.utils.onDetachAction(false, true);
+                }
+                _this._viewer.update();
+                _this._viewer.selectedNode = null;
+            });
+            document.getElementById("ViewerDisconnectAll").addEventListener("click", function (event) {
+                for (var i = 0; i < _this._viewer.root.children.length; i++) {
+                    _this._viewer.selectedNode = _this._viewer.root.children[i];
+                    _this._viewer.utils.onDetachAction(true, false);
+                }
+                _this._viewer.update();
+                _this._viewer.selectedNode = null;
+            });
+            document.getElementById("ViewerReduceAll").addEventListener("click", function (event) {
+                for (var i = 0; i < _this._viewer.root.children.length; i++) {
+                    _this._viewer.selectedNode = _this._viewer.root.children[i];
+                    _this._viewer.utils.onReduceAll(false);
+                }
+                _this._viewer.update();
+                _this._viewer.selectedNode = null;
+            });
+            document.getElementById("ViewerExpandAll").addEventListener("click", function (event) {
+                for (var i = 0; i < _this._viewer.root.children.length; i++) {
+                    _this._viewer.selectedNode = _this._viewer.root.children[i];
+                    _this._viewer.utils.onReduceAll(true);
+                }
+                _this._viewer.update();
+                _this._viewer.selectedNode = null;
+            });
+            // Top toolbar
+            this.saveActionGraphElement = document.getElementById("ToolsButtonIDSaveActionGraph");
+            this.drawSaveActionGraphButton(false);
+            document.getElementById("ResetActionGraphID").addEventListener("click", function (event) {
+                if (confirm("Are you sure?")) {
+                    for (var i = 0; i < _this._viewer.root.children.length; i++) {
+                        _this._viewer.selectedNode = _this._viewer.root.children[i];
+                        _this._viewer.utils.onRemoveBranch();
+                    }
+                    _this._viewer.update();
+                    _this._viewer.selectedNode = null;
+                }
+            });
+            document.getElementById("TestActionGraphID").addEventListener("click", function (event) {
+                _this._viewer.utils.onTestGraph();
+            });
+        }
+        Toolbar.prototype.onResize = function () {
+            this.toolbarElement.style.top = this._viewer.viewerElement.clientHeight + 20 + "px";
+        };
+        Toolbar.prototype.drawSaveActionGraphButton = function (draw) {
+            this.saveActionGraphElement.style.display = draw ? "block" : "none";
+        };
+        return Toolbar;
+    }());
+    ActionsBuilder.Toolbar = Toolbar;
+})(ActionsBuilder || (ActionsBuilder = {}));
 //# sourceMappingURL=actionsbuilder.toolbar.js.map

+ 433 - 433
Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.utils.js

@@ -1,434 +1,434 @@
-var ActionsBuilder;
-(function (ActionsBuilder) {
-    var Utils = (function () {
-        /*
-        * Constructor
-        * @param viewer: the viewer instance
-        */
-        function Utils(viewer) {
-            // Members
-            this.copiedStructure = null;
-            // Configure this
-            this._viewer = viewer;
-        }
-        /*
-        * Tests the graph and reports errors
-        */
-        Utils.prototype.onTestGraph = function () {
-            var _this = this;
-            if (this._viewer.root.children.length === 0) {
-                alert("Please add at least a Trigger and an Action to test the graph");
-            }
-            var onTestTarget = function (targetType, target) {
-                var targetExists = false;
-                var array = _this._viewer.parameters._getTargetFromType(targetType);
-                if (array === null) {
-                    return targetExists;
-                }
-                for (var i = 0; i < array.length; i++) {
-                    if (array[i] === target) {
-                        targetExists = true;
-                        break;
-                    }
-                }
-                return targetExists;
-            };
-            var onNodeError = function (action) {
-                var node = action.node;
-                node.rect.attr("fill", Raphael.rgb(255, 0, 0));
-                return false;
-            };
-            var onTestAction = function (action) {
-                console.log("Testing " + action.name);
-                if (action.combineArray !== null) {
-                    var foundError = false;
-                    for (var i = 0; i < action.combineArray.length; i++) {
-                        if (!onTestAction(action.combineArray[i])) {
-                            foundError = true;
-                        }
-                    }
-                    if (foundError) {
-                        return false;
-                    }
-                }
-                else {
-                    // Test properties
-                    var properties = action.properties;
-                    var propertiesResults = action.propertiesResults;
-                    if (properties !== null) {
-                        var object = null;
-                        var propertyPath = null;
-                        for (var i = 0; i < properties.length; i++) {
-                            // Target
-                            if (properties[i].text === "target" || properties[i].text === "parent") {
-                                object = _this._viewer.parameters._getObjectFromType(properties[i].targetType);
-                                var targetExists = onTestTarget(propertiesResults[i].targetType, propertiesResults[i].value);
-                                if (!targetExists) {
-                                    return onNodeError(action);
-                                }
-                            }
-                            else if (properties[i].text === "propertyPath") {
-                                var property = propertiesResults[i].value;
-                                var effectiveProperty = object;
-                                var p = property.split(".");
-                                for (var j = 0; j < p.length && effectiveProperty !== undefined; j++) {
-                                    effectiveProperty = effectiveProperty[p[j]];
-                                }
-                                if (effectiveProperty === undefined) {
-                                    return onNodeError(action);
-                                }
-                                else {
-                                    propertyPath = effectiveProperty;
-                                }
-                            }
-                            else if (properties[i].text == "value" && propertyPath != null) {
-                                var value = propertiesResults[i].value;
-                                if (!isNaN(propertyPath)) {
-                                    var num = parseFloat(value);
-                                    if (isNaN(num) || value === "") {
-                                        return onNodeError(action);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    var foundError = false;
-                    for (var i = 0; i < action.children.length; i++) {
-                        if (!onTestAction(action.children[i])) {
-                            foundError = true;
-                        }
-                    }
-                    return !foundError;
-                }
-            };
-            var root = this._viewer.root;
-            var foundError = false;
-            for (var i = 0; i < root.children.length; i++) {
-                var trigger = root.children[i];
-                var properties = trigger.properties;
-                // Test properties of trigger (parameter)
-                if (properties !== null && properties.length > 0) {
-                    // Only one property
-                    var parameter = trigger.propertiesResults[0].value;
-                    if (properties[0].targetType !== null) {
-                        // Intersection trigger
-                        if (!onTestTarget("MeshProperties", parameter)) {
-                            foundError = onNodeError(trigger);
-                        }
-                    }
-                    else {
-                        // Key trigger
-                        if (!parameter.match(/[a-z]/)) {
-                            foundError = onNodeError(trigger);
-                        }
-                    }
-                }
-                for (var j = 0; j < trigger.children.length; j++) {
-                    var child = trigger.children[j];
-                    var result = onTestAction(child);
-                    if (!result) {
-                        foundError = true;
-                    }
-                }
-            }
-            if (foundError) {
-                alert("Found error(s). the red nodes contain the error.");
-            }
-            else {
-                alert("No error found.");
-            }
-        };
-        /*
-        * Recursively reduce/expand nodes
-        */
-        Utils.prototype.onReduceAll = function (forceExpand) {
-            if (forceExpand === void 0) { forceExpand = false; }
-            if (this._viewer.selectedNode === null) {
-                return;
-            }
-            var action = this._viewer.selectedNode;
-            if (action.combineArray !== null) {
-                for (var i = 0; i < action.combineArray.length; i++) {
-                    this._viewer.selectedNode = action.combineArray[i];
-                    this.onReduce(forceExpand, !forceExpand);
-                }
-            }
-            else {
-                this.onReduce(forceExpand, !forceExpand);
-            }
-            for (var i = 0; i < action.children.length; i++) {
-                this._viewer.selectedNode = action.children[i];
-                this.onReduceAll(forceExpand);
-            }
-        };
-        /*
-        * Reduces the selected node
-        */
-        Utils.prototype.onReduce = function (forceExpand, forceReduce) {
-            if (forceExpand === void 0) { forceExpand = false; }
-            if (forceReduce === void 0) { forceReduce = false; }
-            if (this._viewer.selectedNode === null) {
-                return;
-            }
-            var node = this._viewer.selectedNode.node;
-            node.rect.stop(node.rect.animation);
-            // Set minimized
-            if (forceExpand === true) {
-                node.minimized = false;
-            }
-            else if (forceReduce === true) {
-                node.minimized = true;
-            }
-            else {
-                node.minimized = !node.minimized;
-            }
-            // Set size
-            if (node.minimized) {
-                node.text.hide();
-                node.rect.attr("width", ActionsBuilder.Viewer.NODE_MINIMIZED_WIDTH * this._viewer.zoom);
-            }
-            else {
-                node.text.show();
-                node.rect.attr("width", ActionsBuilder.Viewer.NODE_WIDTH * this._viewer.zoom);
-            }
-        };
-        /*
-        * Detaches the selected action
-        */
-        Utils.prototype.onDetachAction = function (forceDetach, forceAttach) {
-            var _this = this;
-            if (forceDetach === void 0) { forceDetach = false; }
-            if (forceAttach === void 0) { forceAttach = false; }
-            if (this._viewer.selectedNode === null) {
-                return;
-            }
-            var action = this._viewer.selectedNode;
-            if (forceDetach === true) {
-                action.node.detached = true;
-            }
-            else if (forceAttach === true) {
-                action.node.detached = false;
-            }
-            else {
-                action.node.detached = !action.node.detached;
-            }
-            var onSetColor = function (root, detached) {
-                var rootNode = root.node;
-                rootNode.rect.attr("fill", _this._viewer.getNodeColor(root.type, detached));
-                if (root.combineArray !== null) {
-                    for (var i = 0; i < root.combineArray.length; i++) {
-                        var combineNode = root.combineArray[i].node;
-                        combineNode.rect.attr("fill", _this._viewer.getNodeColor(root.combineArray[i].type, detached));
-                    }
-                }
-                for (var i = 0; i < root.children.length; i++) {
-                    onSetColor(root.children[i], detached);
-                }
-            };
-            onSetColor(action, action.node.detached);
-        };
-        /*
-        * Removes the selected node
-        */
-        Utils.prototype.onRemoveNode = function () {
-            if (this._viewer.selectedNode === null) {
-                return;
-            }
-            var action = this._viewer.selectedNode;
-            var parent = action.parent;
-            // If trigger, remove branch
-            if (action.type === ActionsBuilder.Type.TRIGGER) {
-                this.onRemoveBranch();
-                return;
-            }
-            // If it is a combine hub
-            if (action.type === ActionsBuilder.Type.FLOW_CONTROL && parent !== null && parent.combineArray !== null) {
-                action = parent;
-                parent = action.parent;
-            }
-            // Remove
-            if (parent !== null && parent.combineArray !== null) {
-                parent.removeCombinedAction(action);
-                if (parent.combineArray.length === 0) {
-                    parent.node.text.attr("text", "combine");
-                }
-            }
-            else {
-                if (action.combineArray !== null) {
-                    action.removeChild(action.hub);
-                }
-                action.parent.removeChild(action);
-            }
-            if (action.combineArray !== null) {
-                this._viewer.removeAction(action.hub, false);
-            }
-            this._viewer.removeAction(action, false);
-            // Finish
-            this._viewer.update();
-            this._viewer.parameters.clearParameters();
-            this._viewer.selectedNode = null;
-        };
-        /*
-        * Removes a branch starting from the selected node
-        */
-        Utils.prototype.onRemoveBranch = function () {
-            if (this._viewer.selectedNode === null) {
-                return;
-            }
-            if (this._viewer.selectedNode === this._viewer.root) {
-                alert("Cannot remove the root node");
-                return;
-            }
-            var action = this._viewer.selectedNode;
-            var parent = action.parent;
-            // If combine
-            if (action.parent !== null && action.parent.combineArray !== null) {
-                action = parent;
-                parent = action.parent;
-            }
-            // Remove
-            if (action.combineArray !== null) {
-                action.removeChild(action.hub);
-            }
-            action.parent.removeChild(action);
-            this._viewer.removeAction(action, true);
-            // Finish
-            this._viewer.update();
-            this._viewer.parameters.clearParameters();
-            this._viewer.selectedNode = null;
-        };
-        /*
-        * Copies the selected structure
-        */
-        Utils.prototype.onCopyStructure = function () {
-            if (this._viewer.selectedNode === null) {
-                return;
-            }
-            var structure = this.createJSON(this._viewer.selectedNode);
-            var asText = JSON.stringify(structure);
-            if (window.clipboardData !== undefined) {
-                window.clipboardData.setData("text", asText);
-            }
-            else {
-                this.copiedStructure = asText;
-            }
-        };
-        /*
-        * Pastes the graph structure previously copied
-        */
-        Utils.prototype.onPasteStructure = function () {
-            if (this._viewer.selectedNode === null) {
-                return;
-            }
-            var asText = (window.clipboardData !== undefined) ? window.clipboardData.getData("text") : this.copiedStructure;
-            var isJson = asText.length > 0 && asText[0] == "{" && asText[asText.length - 1] == "}";
-            var structure = JSON.parse(asText);
-            var action = this._viewer.selectedNode;
-            if (structure.type === ActionsBuilder.Type.TRIGGER && action !== this._viewer.root) {
-                alert("You can't paste a trigger if the selected node isn't the root object");
-                return;
-            }
-            if (structure.type !== ActionsBuilder.Type.TRIGGER && action === this._viewer.root) {
-                alert("You can't paste an action or condition if the selected node is the root object");
-                return;
-            }
-            this.loadFromJSON(structure, action);
-            this._viewer.update();
-        };
-        /*
-        * Loads a graph from JSON
-        * @pram graph: the graph structure
-        * @param startAction: the action to start load
-        */
-        Utils.prototype.loadFromJSON = function (graph, startAction) {
-            var _this = this;
-            // If startNode is null, means it replaces all the graph
-            // If not, it comes from a copy/paste
-            if (startAction === null) {
-                for (var i = 0; i < this._viewer.root.children.length; i++) {
-                    this._viewer.removeAction(this._viewer.root.children[i], true);
-                }
-                this._viewer.root.clearChildren();
-            }
-            var load = function (root, parent, detached, combine) {
-                if (parent === null) {
-                    parent = _this._viewer.root;
-                }
-                var newAction = null;
-                if (root.type !== ActionsBuilder.Type.OBJECT && root.type !== ActionsBuilder.Type.SCENE) {
-                    var action = _this._viewer.addAction(parent, root.type, ActionsBuilder.Elements.GetElementFromName(root.name));
-                    for (var i = 0; i < root.properties.length; i++) {
-                        var targetType = root.properties[i].targetType;
-                        if (targetType === undefined) {
-                            targetType = "MeshProperties"; // Default is mesh properties
-                        }
-                        action.propertiesResults[i] = { value: root.properties[i].value, targetType: targetType };
-                    }
-                    var node = action.node;
-                    node.detached = root.detached;
-                    if (detached) {
-                        node.rect.attr("fill", _this._viewer.getNodeColor(action.type, detached));
-                    }
-                    // If combine array
-                    if (root.combine !== undefined) {
-                        for (var i = 0; i < root.combine.length; i++) {
-                            load(root.combine[i], action, detached, true);
-                        }
-                    }
-                    if (!combine) {
-                        parent = parent.children[parent.children.length - 1];
-                    }
-                }
-                for (var i = 0; i < root.children.length; i++) {
-                    load(root.children[i], newAction !== null && newAction.combineArray !== null ? newAction.hub : parent, root.detached, false);
-                }
-            };
-            // Finish
-            load(graph, startAction, false, false);
-            this._viewer.update();
-        };
-        /*
-        * Creates a JSON object starting from a root action
-        * @param root: the root action
-        */
-        Utils.prototype.createJSON = function (root) {
-            var action = {
-                type: root.type,
-                name: root.name,
-                detached: root.node.detached,
-                children: new Array(),
-                combine: new Array(),
-                properties: new Array()
-            };
-            // Set properties
-            for (var i = 0; i < root.properties.length; i++) {
-                action.properties.push({
-                    name: root.properties[i].text,
-                    value: root.propertiesResults[i].value,
-                    targetType: root.propertiesResults[i].targetType
-                });
-            }
-            // If combine
-            if (root.combineArray !== null) {
-                for (var i = 0; i < root.combineArray.length; i++) {
-                    var combinedAction = root.combineArray[i];
-                    action.combine.push(this.createJSON(combinedAction));
-                }
-                root = root.children[0]; // Hub
-            }
-            for (var i = 0; i < root.children.length; i++) {
-                action.children.push(this.createJSON(root.children[i]));
-            }
-            return action;
-        };
-        /*
-        *
-        */
-        Utils.prototype.setElementVisible = function (element, visible) {
-            element.style.display = visible ? "block" : "none";
-        };
-        return Utils;
-    })();
-    ActionsBuilder.Utils = Utils;
-})(ActionsBuilder || (ActionsBuilder = {}));
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    var Utils = (function () {
+        /*
+        * Constructor
+        * @param viewer: the viewer instance
+        */
+        function Utils(viewer) {
+            // Members
+            this.copiedStructure = null;
+            // Configure this
+            this._viewer = viewer;
+        }
+        /*
+        * Tests the graph and reports errors
+        */
+        Utils.prototype.onTestGraph = function () {
+            var _this = this;
+            if (this._viewer.root.children.length === 0) {
+                alert("Please add at least a Trigger and an Action to test the graph");
+            }
+            var onTestTarget = function (targetType, target) {
+                var targetExists = false;
+                var array = _this._viewer.parameters._getTargetFromType(targetType);
+                if (array === null) {
+                    return targetExists;
+                }
+                for (var i = 0; i < array.length; i++) {
+                    if (array[i] === target) {
+                        targetExists = true;
+                        break;
+                    }
+                }
+                return targetExists;
+            };
+            var onNodeError = function (action) {
+                var node = action.node;
+                node.rect.attr("fill", Raphael.rgb(255, 0, 0));
+                return false;
+            };
+            var onTestAction = function (action) {
+                console.log("Testing " + action.name);
+                if (action.combineArray !== null) {
+                    var foundError = false;
+                    for (var i = 0; i < action.combineArray.length; i++) {
+                        if (!onTestAction(action.combineArray[i])) {
+                            foundError = true;
+                        }
+                    }
+                    if (foundError) {
+                        return false;
+                    }
+                }
+                else {
+                    // Test properties
+                    var properties = action.properties;
+                    var propertiesResults = action.propertiesResults;
+                    if (properties !== null) {
+                        var object = null;
+                        var propertyPath = null;
+                        for (var i = 0; i < properties.length; i++) {
+                            // Target
+                            if (properties[i].text === "target" || properties[i].text === "parent") {
+                                object = _this._viewer.parameters._getObjectFromType(properties[i].targetType);
+                                var targetExists = onTestTarget(propertiesResults[i].targetType, propertiesResults[i].value);
+                                if (!targetExists) {
+                                    return onNodeError(action);
+                                }
+                            }
+                            else if (properties[i].text === "propertyPath") {
+                                var property = propertiesResults[i].value;
+                                var effectiveProperty = object;
+                                var p = property.split(".");
+                                for (var j = 0; j < p.length && effectiveProperty !== undefined; j++) {
+                                    effectiveProperty = effectiveProperty[p[j]];
+                                }
+                                if (effectiveProperty === undefined) {
+                                    return onNodeError(action);
+                                }
+                                else {
+                                    propertyPath = effectiveProperty;
+                                }
+                            }
+                            else if (properties[i].text == "value" && propertyPath != null) {
+                                var value = propertiesResults[i].value;
+                                if (!isNaN(propertyPath)) {
+                                    var num = parseFloat(value);
+                                    if (isNaN(num) || value === "") {
+                                        return onNodeError(action);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    var foundError = false;
+                    for (var i = 0; i < action.children.length; i++) {
+                        if (!onTestAction(action.children[i])) {
+                            foundError = true;
+                        }
+                    }
+                    return !foundError;
+                }
+            };
+            var root = this._viewer.root;
+            var foundError = false;
+            for (var i = 0; i < root.children.length; i++) {
+                var trigger = root.children[i];
+                var properties = trigger.properties;
+                // Test properties of trigger (parameter)
+                if (properties !== null && properties.length > 0) {
+                    // Only one property
+                    var parameter = trigger.propertiesResults[0].value;
+                    if (properties[0].targetType !== null) {
+                        // Intersection trigger
+                        if (!onTestTarget("MeshProperties", parameter)) {
+                            foundError = onNodeError(trigger);
+                        }
+                    }
+                    else {
+                        // Key trigger
+                        if (!parameter.match(/[a-z]/)) {
+                            foundError = onNodeError(trigger);
+                        }
+                    }
+                }
+                for (var j = 0; j < trigger.children.length; j++) {
+                    var child = trigger.children[j];
+                    var result = onTestAction(child);
+                    if (!result) {
+                        foundError = true;
+                    }
+                }
+            }
+            if (foundError) {
+                alert("Found error(s). the red nodes contain the error.");
+            }
+            else {
+                alert("No error found.");
+            }
+        };
+        /*
+        * Recursively reduce/expand nodes
+        */
+        Utils.prototype.onReduceAll = function (forceExpand) {
+            if (forceExpand === void 0) { forceExpand = false; }
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            var action = this._viewer.selectedNode;
+            if (action.combineArray !== null) {
+                for (var i = 0; i < action.combineArray.length; i++) {
+                    this._viewer.selectedNode = action.combineArray[i];
+                    this.onReduce(forceExpand, !forceExpand);
+                }
+            }
+            else {
+                this.onReduce(forceExpand, !forceExpand);
+            }
+            for (var i = 0; i < action.children.length; i++) {
+                this._viewer.selectedNode = action.children[i];
+                this.onReduceAll(forceExpand);
+            }
+        };
+        /*
+        * Reduces the selected node
+        */
+        Utils.prototype.onReduce = function (forceExpand, forceReduce) {
+            if (forceExpand === void 0) { forceExpand = false; }
+            if (forceReduce === void 0) { forceReduce = false; }
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            var node = this._viewer.selectedNode.node;
+            node.rect.stop(node.rect.animation);
+            // Set minimized
+            if (forceExpand === true) {
+                node.minimized = false;
+            }
+            else if (forceReduce === true) {
+                node.minimized = true;
+            }
+            else {
+                node.minimized = !node.minimized;
+            }
+            // Set size
+            if (node.minimized) {
+                node.text.hide();
+                node.rect.attr("width", ActionsBuilder.Viewer.NODE_MINIMIZED_WIDTH * this._viewer.zoom);
+            }
+            else {
+                node.text.show();
+                node.rect.attr("width", ActionsBuilder.Viewer.NODE_WIDTH * this._viewer.zoom);
+            }
+        };
+        /*
+        * Detaches the selected action
+        */
+        Utils.prototype.onDetachAction = function (forceDetach, forceAttach) {
+            var _this = this;
+            if (forceDetach === void 0) { forceDetach = false; }
+            if (forceAttach === void 0) { forceAttach = false; }
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            var action = this._viewer.selectedNode;
+            if (forceDetach === true) {
+                action.node.detached = true;
+            }
+            else if (forceAttach === true) {
+                action.node.detached = false;
+            }
+            else {
+                action.node.detached = !action.node.detached;
+            }
+            var onSetColor = function (root, detached) {
+                var rootNode = root.node;
+                rootNode.rect.attr("fill", _this._viewer.getNodeColor(root.type, detached));
+                if (root.combineArray !== null) {
+                    for (var i = 0; i < root.combineArray.length; i++) {
+                        var combineNode = root.combineArray[i].node;
+                        combineNode.rect.attr("fill", _this._viewer.getNodeColor(root.combineArray[i].type, detached));
+                    }
+                }
+                for (var i = 0; i < root.children.length; i++) {
+                    onSetColor(root.children[i], detached);
+                }
+            };
+            onSetColor(action, action.node.detached);
+        };
+        /*
+        * Removes the selected node
+        */
+        Utils.prototype.onRemoveNode = function () {
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            var action = this._viewer.selectedNode;
+            var parent = action.parent;
+            // If trigger, remove branch
+            if (action.type === ActionsBuilder.Type.TRIGGER) {
+                this.onRemoveBranch();
+                return;
+            }
+            // If it is a combine hub
+            if (action.type === ActionsBuilder.Type.FLOW_CONTROL && parent !== null && parent.combineArray !== null) {
+                action = parent;
+                parent = action.parent;
+            }
+            // Remove
+            if (parent !== null && parent.combineArray !== null) {
+                parent.removeCombinedAction(action);
+                if (parent.combineArray.length === 0) {
+                    parent.node.text.attr("text", "combine");
+                }
+            }
+            else {
+                if (action.combineArray !== null) {
+                    action.removeChild(action.hub);
+                }
+                action.parent.removeChild(action);
+            }
+            if (action.combineArray !== null) {
+                this._viewer.removeAction(action.hub, false);
+            }
+            this._viewer.removeAction(action, false);
+            // Finish
+            this._viewer.update();
+            this._viewer.parameters.clearParameters();
+            this._viewer.selectedNode = null;
+        };
+        /*
+        * Removes a branch starting from the selected node
+        */
+        Utils.prototype.onRemoveBranch = function () {
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            if (this._viewer.selectedNode === this._viewer.root) {
+                alert("Cannot remove the root node");
+                return;
+            }
+            var action = this._viewer.selectedNode;
+            var parent = action.parent;
+            // If combine
+            if (action.parent !== null && action.parent.combineArray !== null) {
+                action = parent;
+                parent = action.parent;
+            }
+            // Remove
+            if (action.combineArray !== null) {
+                action.removeChild(action.hub);
+            }
+            action.parent.removeChild(action);
+            this._viewer.removeAction(action, true);
+            // Finish
+            this._viewer.update();
+            this._viewer.parameters.clearParameters();
+            this._viewer.selectedNode = null;
+        };
+        /*
+        * Copies the selected structure
+        */
+        Utils.prototype.onCopyStructure = function () {
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            var structure = this.createJSON(this._viewer.selectedNode);
+            var asText = JSON.stringify(structure);
+            if (window.clipboardData !== undefined) {
+                window.clipboardData.setData("text", asText);
+            }
+            else {
+                this.copiedStructure = asText;
+            }
+        };
+        /*
+        * Pastes the graph structure previously copied
+        */
+        Utils.prototype.onPasteStructure = function () {
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            var asText = (window.clipboardData !== undefined) ? window.clipboardData.getData("text") : this.copiedStructure;
+            var isJson = asText.length > 0 && asText[0] == "{" && asText[asText.length - 1] == "}";
+            var structure = JSON.parse(asText);
+            var action = this._viewer.selectedNode;
+            if (structure.type === ActionsBuilder.Type.TRIGGER && action !== this._viewer.root) {
+                alert("You can't paste a trigger if the selected node isn't the root object");
+                return;
+            }
+            if (structure.type !== ActionsBuilder.Type.TRIGGER && action === this._viewer.root) {
+                alert("You can't paste an action or condition if the selected node is the root object");
+                return;
+            }
+            this.loadFromJSON(structure, action);
+            this._viewer.update();
+        };
+        /*
+        * Loads a graph from JSON
+        * @pram graph: the graph structure
+        * @param startAction: the action to start load
+        */
+        Utils.prototype.loadFromJSON = function (graph, startAction) {
+            var _this = this;
+            // If startNode is null, means it replaces all the graph
+            // If not, it comes from a copy/paste
+            if (startAction === null) {
+                for (var i = 0; i < this._viewer.root.children.length; i++) {
+                    this._viewer.removeAction(this._viewer.root.children[i], true);
+                }
+                this._viewer.root.clearChildren();
+            }
+            var load = function (root, parent, detached, combine) {
+                if (parent === null) {
+                    parent = _this._viewer.root;
+                }
+                var newAction = null;
+                if (root.type !== ActionsBuilder.Type.OBJECT && root.type !== ActionsBuilder.Type.SCENE) {
+                    var action = _this._viewer.addAction(parent, root.type, ActionsBuilder.Elements.GetElementFromName(root.name));
+                    for (var i = 0; i < root.properties.length; i++) {
+                        var targetType = root.properties[i].targetType;
+                        if (targetType === undefined) {
+                            targetType = "MeshProperties"; // Default is mesh properties
+                        }
+                        action.propertiesResults[i] = { value: root.properties[i].value, targetType: targetType };
+                    }
+                    var node = action.node;
+                    node.detached = root.detached;
+                    if (detached) {
+                        node.rect.attr("fill", _this._viewer.getNodeColor(action.type, detached));
+                    }
+                    // If combine array
+                    if (root.combine !== undefined) {
+                        for (var i = 0; i < root.combine.length; i++) {
+                            load(root.combine[i], action, detached, true);
+                        }
+                    }
+                    if (!combine) {
+                        parent = parent.children[parent.children.length - 1];
+                    }
+                }
+                for (var i = 0; i < root.children.length; i++) {
+                    load(root.children[i], newAction !== null && newAction.combineArray !== null ? newAction.hub : parent, root.detached, false);
+                }
+            };
+            // Finish
+            load(graph, startAction, false, false);
+            this._viewer.update();
+        };
+        /*
+        * Creates a JSON object starting from a root action
+        * @param root: the root action
+        */
+        Utils.prototype.createJSON = function (root) {
+            var action = {
+                type: root.type,
+                name: root.name,
+                detached: root.node.detached,
+                children: new Array(),
+                combine: new Array(),
+                properties: new Array()
+            };
+            // Set properties
+            for (var i = 0; i < root.properties.length; i++) {
+                action.properties.push({
+                    name: root.properties[i].text,
+                    value: root.propertiesResults[i].value,
+                    targetType: root.propertiesResults[i].targetType
+                });
+            }
+            // If combine
+            if (root.combineArray !== null) {
+                for (var i = 0; i < root.combineArray.length; i++) {
+                    var combinedAction = root.combineArray[i];
+                    action.combine.push(this.createJSON(combinedAction));
+                }
+                root = root.children[0]; // Hub
+            }
+            for (var i = 0; i < root.children.length; i++) {
+                action.children.push(this.createJSON(root.children[i]));
+            }
+            return action;
+        };
+        /*
+        *
+        */
+        Utils.prototype.setElementVisible = function (element, visible) {
+            element.style.display = visible ? "block" : "none";
+        };
+        return Utils;
+    }());
+    ActionsBuilder.Utils = Utils;
+})(ActionsBuilder || (ActionsBuilder = {}));
 //# sourceMappingURL=actionsbuilder.utils.js.map

文件差異過大導致無法顯示
+ 631 - 647
Exporters/3ds Max/ActionsBuilder/Sources/actionsbuilder.viewer.js


文件差異過大導致無法顯示
+ 47131 - 24102
Exporters/3ds Max/ActionsBuilder/Sources/babylon.max.js


+ 0 - 48
Exporters/3ds Max/ActionsBuilder/Sources/fonts/SinkinSans/SinkinSans_NOTICE.txt

@@ -1,48 +0,0 @@
-
-=== SINKIN SANS 100 THIN ===
-=== SINKIN SANS 100 THIN ITALIC ===
-=== SINKIN SANS 200 X LIGHT ===
-=== SINKIN SANS 200 X LIGHT ITALIC ===
-=== SINKIN SANS 300 LIGHT ===
-=== SINKIN SANS 300 LIGHT ITALIC ===
-=== SINKIN SANS 400 REGULAR ===
-=== SINKIN SANS 400 ITALIC ===
-=== SINKIN SANS 500 MEDIUM ===
-=== SINKIN SANS 500 MEDIUM ITALIC ===
-=== SINKIN SANS 600 SEMIBOLD ===
-=== SINKIN SANS 600 SEMIBOLD ITALIC ===
-=== SINKIN SANS 700 BOLD ===
-=== SINKIN SANS 700 BOLD ITALIC ===
-=== SINKIN SANS 800 BLACK ===
-=== SINKIN SANS 800 BLACK ITALIC ===
-=== SINKIN SANS 900 X BLACK ===
-=== SINKIN SANS 900 X BLACK ITALIC ===
-
-Keith Bates / K-Type © 2014 (version 1.1)
-www.k-type.com  -  info@k-type.com
-
-SINKIN SANS is a simple, pleasantly proportioned sans serif with tiny, inconspicuous notches that sink into verticals at the intersections of strokes adding highlights to congested corners. The incisions make right angles appear sharper and improve definition in more intricate glyphs. Although the nicks are barely noticeable they add emphasis to outlines and give a lift to shady nooks.
-
-------------------------------------------------
-
-== Licence Information ==
-
-All weights of SINKIN SANS are totally free for commercial and personal use as desktop and web fonts. For @font-face users, a link to www.k-type.com somewhere on your site is requested, elsewhere a credit to K-Type is appreciated.
-
-You can freely distribute and modify SINKIN SANS provided the original copyright, license information and details of any modifications are included. SINKIN SANS is gifted 'as is', without warranty. SINKIN SANS is a trademark of K-Type. Licensed under the Apache License, Version 2.0
-
-http://www.apache.org/licenses/LICENSE-2.0.html
-
-------------------------------------------------
-
-== Installing Fonts ==
-
-Fonts are placed in your operating system's Fonts folder and will be made available to all the applications or programs you use.
-
-= Windows =
-Put the .ttf or .otf font file into C:\Windows\Fonts, or right-click on the font files > Install
-
-= Mac =
-Put the .ttf or .otf font file into /Library/Fonts
-
-------------------------------------------------

文件差異過大導致無法顯示
+ 97 - 94
Exporters/3ds Max/ActionsBuilder/Sources/index-debug.html


+ 191 - 191
Exporters/3ds Max/ActionsBuilder/Sources/index.css

@@ -1,191 +1,191 @@
-html, body {
-  width: 100%;
-  height: 100%;
-
-  max-width: 100%;
-  max-height: 100%;
-
-  /*background: rgb(64, 64, 64);*/
-
-  overflow: hidden;
-  font-family: "Sinkin Sans Light";
-}
-
-* {
-  position: relative;
-}
-
-#ParentContainerID {
-    height: 100%;
-    width: 100%;
-
-    max-height: 100%;
-    max-width: 100%;
-
-    display: inline-block;
-}
-
-#ListsElementID {
-    width: 25%;
-    height: 100%;
-    
-    max-width: 25%;
-    max-height: 100%;
-
-    background: rgb(64, 64, 64);
-
-    float: left;
-    overflow-y: scroll;
-    overflow-x: hidden;
-}
-
-#GraphContainerID {
-    width: 50%;
-    max-width: 50%;
-
-    float: left;
-    position: relative;
-}
-
-#GraphElementID {
-    position: absolute;
-
-    width: 100%;
-    height: 100%;
-
-    overflow-y: auto;
-    overflow-x: auto;
-
-    max-width: 100%;
-    max-height: 100%;
-}
-
-#ToolbarElementID {
-    position: absolute;
-
-    width: 100%;
-    height: 45px;
-
-    max-width: 100%;
-    max-height: 42px;
-
-    float: left;
-    background: rgb(0, 0, 0);
-
-    vertical-align: middle;
-}
-
-#ToolbarElementID li {
-    color: white;
-    margin-left: 2em;
-    margin-top: 1em;
-}
-
-#ParametersContainerID {
-    width: 25%;
-    height: 100%;
-
-    max-width: 25%;
-    max-height: 100%;
-
-    float: right;
-    overflow-y: auto;
-}
-
-#ParametersElementID {
-    width: 100%;
-    max-width: 100%;
-
-    background: rgb(32, 32, 32);
-    overflow: auto;
-}
-
-#ParametersHelpElementID {
-    background: rgb(0, 0, 0);
-
-    font-family: "Sinkin Sans Light";
-    font-size: 12px;
-    font-style: italic;
-
-    text-align: center;
-    text-anchor: middle;
-    color: white;
-}
-
-.ParametersElementNodeClass {
-    font-size: 11px;
-    height: 25px;
-    margin-top: 10px;
-    border: 1px solid white;
-
-    text-align: center;
-
-    margin-left: auto;
-    margin-right: auto;
-    width: 90%;
-}
-.ParametersElementNodeTextClass {
-    width: 100%;
-    height: 100%;
-
-    vertical-align: middle;
-    line-height: 25px;
-}
-.ParametersElementSeparatorClass {
-    width: 90%;
-}
-.ParametersElementTitleClass {
-    margin-left: 3em;
-    display: block;
-    color: white;
-    font-size: 11px;
-}
-.ParametersElementSelectClass {
-    margin-top: 15px;
-
-    width: 80%;
-    height: 25px;
-
-    display: block;
-    font-size: 11px;
-    margin-left: 3em;
-}
-.ParametersElementInputClass {
-    margin-top: 15px;
-
-    width: 80%;
-    height: 15px;
-
-    display: block;
-    font-size: 11px;
-    margin-left: 3em;
-}
-
-/*
-UL & LI (toolbar & top buttons)
-*/
-#ToolsButtonsID {
-    position: relative;
-
-    width: 100%;
-    height: 25px;
-
-    max-width: 100%;
-    max-height: 25px;
-}
-
-ul {
-  padding-left: 1em;
-  margin-bottom: 0.5em;
-  margin-top: 0.0em;
-}
-ul li {
-  list-style-type: none;
-  display: inline-block;
-  margin-right: 3em;
-  cursor: pointer;
-  font-size: 12px;
-}
-ul li:last-child {
-  margin-right: 0;
-}
+html, body {
+  width: 100%;
+  height: 100%;
+
+  max-width: 100%;
+  max-height: 100%;
+
+  /*background: rgb(64, 64, 64);*/
+
+  overflow: hidden;
+  font-family: "Sinkin Sans Light";
+}
+
+* {
+  position: relative;
+}
+
+#ParentContainerID {
+    height: 100%;
+    width: 100%;
+
+    max-height: 100%;
+    max-width: 100%;
+
+    display: inline-block;
+}
+
+#ListsElementID {
+    width: 25%;
+    height: 100%;
+    
+    max-width: 25%;
+    max-height: 100%;
+
+    background: rgb(64, 64, 64);
+
+    float: left;
+    overflow-y: scroll;
+    overflow-x: hidden;
+}
+
+#GraphContainerID {
+    width: 50%;
+    max-width: 50%;
+
+    float: left;
+    position: relative;
+}
+
+#GraphElementID {
+    position: absolute;
+
+    width: 100%;
+    height: 100%;
+
+    overflow-y: auto;
+    overflow-x: auto;
+
+    max-width: 100%;
+    max-height: 100%;
+}
+
+#ToolbarElementID {
+    position: absolute;
+
+    width: 100%;
+    height: 45px;
+
+    max-width: 100%;
+    max-height: 42px;
+
+    float: left;
+    background: rgb(0, 0, 0);
+
+    vertical-align: middle;
+}
+
+#ToolbarElementID li {
+    color: white;
+    margin-left: 2em;
+    margin-top: 1em;
+}
+
+#ParametersContainerID {
+    width: 25%;
+    height: 100%;
+
+    max-width: 25%;
+    max-height: 100%;
+
+    float: right;
+    overflow-y: auto;
+}
+
+#ParametersElementID {
+    width: 100%;
+    max-width: 100%;
+
+    background: rgb(32, 32, 32);
+    overflow: auto;
+}
+
+#ParametersHelpElementID {
+    background: rgb(0, 0, 0);
+
+    font-family: "Sinkin Sans Light";
+    font-size: 12px;
+    font-style: italic;
+
+    text-align: center;
+    text-anchor: middle;
+    color: white;
+}
+
+.ParametersElementNodeClass {
+    font-size: 11px;
+    height: 25px;
+    margin-top: 10px;
+    border: 1px solid white;
+
+    text-align: center;
+
+    margin-left: auto;
+    margin-right: auto;
+    width: 90%;
+}
+.ParametersElementNodeTextClass {
+    width: 100%;
+    height: 100%;
+
+    vertical-align: middle;
+    line-height: 25px;
+}
+.ParametersElementSeparatorClass {
+    width: 90%;
+}
+.ParametersElementTitleClass {
+    margin-left: 3em;
+    display: block;
+    color: white;
+    font-size: 11px;
+}
+.ParametersElementSelectClass {
+    margin-top: 15px;
+
+    width: 80%;
+    height: 25px;
+
+    display: block;
+    font-size: 11px;
+    margin-left: 3em;
+}
+.ParametersElementInputClass {
+    margin-top: 15px;
+
+    width: 80%;
+    height: 15px;
+
+    display: block;
+    font-size: 11px;
+    margin-left: 3em;
+}
+
+/*
+UL & LI (toolbar & top buttons)
+*/
+#ToolsButtonsID {
+    position: relative;
+
+    width: 100%;
+    height: 25px;
+
+    max-width: 100%;
+    max-height: 25px;
+}
+
+ul {
+  padding-left: 1em;
+  margin-bottom: 0.5em;
+  margin-top: 0.0em;
+}
+ul li {
+  list-style-type: none;
+  display: inline-block;
+  margin-right: 3em;
+  cursor: pointer;
+  font-size: 12px;
+}
+ul li:last-child {
+  margin-right: 0;
+}

+ 72 - 72
Exporters/3ds Max/ActionsBuilder/Sources/index.html

@@ -1,72 +1,72 @@
-<!-- saved from url=(0014)about:internet -->
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml">
-
-<head>
-    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
-    <title>Actions Builder</title>
-
-    <!-- CSS FILES -->
-    <link href="./index.css" rel="stylesheet" />
-    <link href="./fonts.css" rel="stylesheet" />
-
-</head>
-
-<body>
-
-    <!-- PARENT CONTAINER -->
-    <div id="ParentContainerID">
-
-        <ul id="ToolsButtonsID">
-            <li id="ToolsButtonIDSaveActionGraph">save action graph</li>
-            <li id="ResetActionGraphID">reset action graph</li>
-            <li id="TestActionGraphID">test action graph</li>
-        </ul>
-
-        <!-- LIST CONTAINER -->
-        <div id="ListsElementID">
-            <div id="TriggersListID"></div>
-            <div id="ActionsListID"></div>
-            <div id="FlowActionsListID"></div>
-        </div>
-
-        <!-- GRAPH CONTAINER -->
-        <div id="GraphContainerID">
-            <div id="GraphElementID"></div>
-
-            <div id="ToolbarElementID">
-                <ul>
-                    <li id="ViewerReduceAll">reduce all</li>
-                    <li id="ViewerExpandAll">expand all</li>
-                    <li id="ViewerDisconnectAll">disconnect all</li>
-                    <li id="ViewerReconnectAll">reconnect all</li>
-                    <li class="border" style="width: 15px; text-align: center" id="ViewerDeZoomID"> - </li>
-                    <li class="border" style="width: 15px; text-align: center" id="ViewerZoomID"> + </li>
-                </ul>
-            </div>
-        </div>
-
-        <!-- PARAMETERS CONTAINER -->
-        <div id="ParametersContainerID">
-            <div id="ParametersElementID"></div>
-            <div id="ParametersHelpElementID"></div>
-        </div>
-
-    </div>
-
-    <canvas id="RenderCanvasID" style="display:none;"></canvas>
-    <input id="ActionsBuilderObjectName" type="hidden" />
-    <input id="ActionsBuilderJSON" type="hidden" />
-
-    <!-- JS FILES -->
-    <script src="raphael.js" type="text/javascript"></script>
-    <script src="babylon.max.js" type="text/javascript"></script>
-    <script src="actionsbuilder.max.js" type="text/javascript"></script>
-
-    <script type="text/javascript">
-        run();
-    </script>
-
-</body>
-
-</html>
+<!-- saved from url=(0014)about:internet -->
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+    <title>Actions Builder</title>
+
+    <!-- CSS FILES -->
+    <link href="./index.css" rel="stylesheet" />
+    <link href="./fonts.css" rel="stylesheet" />
+
+</head>
+
+<body>
+
+    <!-- PARENT CONTAINER -->
+    <div id="ParentContainerID">
+
+        <ul id="ToolsButtonsID">
+            <li id="ToolsButtonIDSaveActionGraph">save action graph</li>
+            <li id="ResetActionGraphID">reset action graph</li>
+            <li id="TestActionGraphID">test action graph</li>
+        </ul>
+
+        <!-- LIST CONTAINER -->
+        <div id="ListsElementID">
+            <div id="TriggersListID"></div>
+            <div id="ActionsListID"></div>
+            <div id="FlowActionsListID"></div>
+        </div>
+
+        <!-- GRAPH CONTAINER -->
+        <div id="GraphContainerID">
+            <div id="GraphElementID"></div>
+
+            <div id="ToolbarElementID">
+                <ul>
+                    <li id="ViewerReduceAll">reduce all</li>
+                    <li id="ViewerExpandAll">expand all</li>
+                    <li id="ViewerDisconnectAll">disconnect all</li>
+                    <li id="ViewerReconnectAll">reconnect all</li>
+                    <li class="border" style="width: 15px; text-align: center" id="ViewerDeZoomID"> - </li>
+                    <li class="border" style="width: 15px; text-align: center" id="ViewerZoomID"> + </li>
+                </ul>
+            </div>
+        </div>
+
+        <!-- PARAMETERS CONTAINER -->
+        <div id="ParametersContainerID">
+            <div id="ParametersElementID"></div>
+            <div id="ParametersHelpElementID"></div>
+        </div>
+
+    </div>
+
+    <canvas id="RenderCanvasID" style="display:none;"></canvas>
+    <input id="ActionsBuilderObjectName" type="hidden" />
+    <input id="ActionsBuilderJSON" type="hidden" />
+
+    <!-- JS FILES -->
+    <script src="raphael.js" type="text/javascript"></script>
+    <script src="babylon.max.js" type="text/javascript"></script>
+    <script src="actionsbuilder.max.js" type="text/javascript"></script>
+
+    <script type="text/javascript">
+        run();
+    </script>
+
+</body>
+
+</html>

+ 62 - 0
Exporters/3ds Max/ActionsBuilder/actionsbuilder.actionNode.js

@@ -0,0 +1,62 @@
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    var Node = (function () {
+        function Node() {
+            this.rect = null;
+            this.text = null;
+            this.line = null;
+            this.detached = false;
+            this.minimized = false;
+        }
+        Node.prototype.isPointInside = function (x, y) {
+            return this.rect.isPointInside(x, y) || this.text.isPointInside(x, y);
+        };
+        return Node;
+    })();
+    ActionsBuilder.Node = Node;
+    var Action = (function () {
+        function Action(node) {
+            this.parent = null;
+            this.children = new Array();
+            this.name = "";
+            this.type = ActionsBuilder.Type.OBJECT;
+            this.properties = new Array();
+            this.propertiesResults = new Array();
+            this.combineArray = null;
+            this.hub = null;
+            this.combineAction = null;
+            this.node = node;
+        }
+        Action.prototype.removeCombinedAction = function (action) {
+            if (action === null || this.combineArray === null) {
+                return false;
+            }
+            var index = this.combineArray.indexOf(action);
+            if (index !== -1) {
+                this.combineArray.splice(index, 1);
+            }
+            return false;
+        };
+        Action.prototype.addChild = function (child) {
+            if (child === null) {
+                return false;
+            }
+            this.children.push(child);
+            child.parent = this;
+            return true;
+        };
+        Action.prototype.removeChild = function (child) {
+            var indice = this.children.indexOf(child);
+            if (indice !== -1) {
+                this.children.splice(indice, 1);
+                return true;
+            }
+            return false;
+        };
+        Action.prototype.clearChildren = function () {
+            this.children = new Array();
+        };
+        return Action;
+    })();
+    ActionsBuilder.Action = Action;
+})(ActionsBuilder || (ActionsBuilder = {}));

+ 100 - 100
Exporters/3ds Max/ActionsBuilder/actionsbuilder.actionNode.ts

@@ -1,101 +1,101 @@
-module ActionsBuilder {
-    export class Node {
-        public rect: Rect = null;
-        public text: Text = null;
-        public line: Path = null;
-
-        public detached: boolean = false;
-        public minimized: boolean = false;
-
-        constructor()
-        { }
-
-        /**
-        * Returns if the point (x, y) is inside the text or rect
-        * @param x: the x position of the point
-        * @param y: the y position of the point
-        */
-        public isPointInside(x: number, y: number): boolean {
-            return this.rect.isPointInside(x, y) || this.text.isPointInside(x, y);
-        }
-    }
-
-    export class Action {
-        public node: Node;
-        public parent: Action = null;
-        public children: Array<Action> = new Array<Action>();
-
-        public name: string = "";
-        public type: number = Type.OBJECT;
-
-        public properties: Array<ElementProperty> = new Array<ElementProperty>();
-        public propertiesResults: Array<ElementPropertyResult> = new Array<ElementPropertyResult>();
-
-        public combineArray: Array<Action> = null;
-        public hub: Action = null;
-        public combineAction: Action = null;
-
-        /**
-        * Constructor
-        * @param node: The associated node to draw in the viewer
-        */
-        constructor(node: Node) {
-            this.node = node;
-        }
-        
-        /*
-        * Removes a combined action from the combine array
-        * @param action: the action to remove
-        */
-        public removeCombinedAction(action: Action): boolean {
-            if (action === null || this.combineArray === null) {
-                return false;
-            }
-
-            var index = this.combineArray.indexOf(action);
-            if (index !== -1) {
-                this.combineArray.splice(index, 1);
-            }
-
-            return false;
-        }
-
-        /*
-        * Adds a child
-        * @param child: the action to add as child
-        */
-        public addChild(child: Action): boolean {
-            if (child === null) {
-                return false;
-            }
-
-            this.children.push(child);
-            child.parent = this;
-
-            return true;
-        }
-
-        /*
-        * Removes the given action to children
-        * @param child: the child to remove
-        */
-        public removeChild(child: Action): boolean {
-            var indice = this.children.indexOf(child);
-
-            if (indice !== -1) {
-                this.children.splice(indice, 1);
-                return true;
-            }
-
-            return false;
-        }
-
-        /*
-        * Clears the children's array
-        */
-        public clearChildren(): void {
-            this.children = new Array<Action>();
-        }
-
-    }
+module ActionsBuilder {
+    export class Node {
+        public rect: Rect = null;
+        public text: Text = null;
+        public line: Path = null;
+
+        public detached: boolean = false;
+        public minimized: boolean = false;
+
+        constructor()
+        { }
+
+        /**
+        * Returns if the point (x, y) is inside the text or rect
+        * @param x: the x position of the point
+        * @param y: the y position of the point
+        */
+        public isPointInside(x: number, y: number): boolean {
+            return this.rect.isPointInside(x, y) || this.text.isPointInside(x, y);
+        }
+    }
+
+    export class Action {
+        public node: Node;
+        public parent: Action = null;
+        public children: Array<Action> = new Array<Action>();
+
+        public name: string = "";
+        public type: number = Type.OBJECT;
+
+        public properties: Array<ElementProperty> = new Array<ElementProperty>();
+        public propertiesResults: Array<ElementPropertyResult> = new Array<ElementPropertyResult>();
+
+        public combineArray: Array<Action> = null;
+        public hub: Action = null;
+        public combineAction: Action = null;
+
+        /**
+        * Constructor
+        * @param node: The associated node to draw in the viewer
+        */
+        constructor(node: Node) {
+            this.node = node;
+        }
+        
+        /*
+        * Removes a combined action from the combine array
+        * @param action: the action to remove
+        */
+        public removeCombinedAction(action: Action): boolean {
+            if (action === null || this.combineArray === null) {
+                return false;
+            }
+
+            var index = this.combineArray.indexOf(action);
+            if (index !== -1) {
+                this.combineArray.splice(index, 1);
+            }
+
+            return false;
+        }
+
+        /*
+        * Adds a child
+        * @param child: the action to add as child
+        */
+        public addChild(child: Action): boolean {
+            if (child === null) {
+                return false;
+            }
+
+            this.children.push(child);
+            child.parent = this;
+
+            return true;
+        }
+
+        /*
+        * Removes the given action to children
+        * @param child: the child to remove
+        */
+        public removeChild(child: Action): boolean {
+            var indice = this.children.indexOf(child);
+
+            if (indice !== -1) {
+                this.children.splice(indice, 1);
+                return true;
+            }
+
+            return false;
+        }
+
+        /*
+        * Clears the children's array
+        */
+        public clearChildren(): void {
+            this.children = new Array<Action>();
+        }
+
+    }
 }

+ 104 - 0
Exporters/3ds Max/ActionsBuilder/actionsbuilder.contextMenu.js

@@ -0,0 +1,104 @@
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    var ContextMenu = (function () {
+        function ContextMenu(viewer) {
+            this.showing = false;
+            this.savedColor = Raphael.rgb(255, 255, 255);
+            this.overColor = Raphael.rgb(140, 200, 230);
+            this._viewer = null;
+            this.elements = [
+                { text: "Reduce", node: null, action: "onReduce" },
+                { text: "Delete", node: null, action: "onRemoveNode" },
+                { text: "Delete branch", node: null, action: "onRemoveBranch" },
+                { text: "Connect / Disconnect", node: null, action: "onDetachAction" },
+                { text: "Copy", node: null, action: "onCopyStructure" },
+                { text: "Paste", node: null, action: "onPasteStructure" },
+                { text: "", node: null, action: null }
+            ];
+            this._viewer = viewer;
+            this.attachControl(this._viewer.paper.canvas);
+        }
+        ContextMenu.prototype.attachControl = function (element) {
+            var _this = this;
+            var onClick = function (event) {
+                var x = _this._viewer.mousex;
+                var y = _this._viewer.mousey;
+                if (_this.showing) {
+                    for (var i = 0; i < _this.elements.length; i++) {
+                        var element = _this.elements[i];
+                        if (element.action && element.node.rect.isPointInside(x, y)) {
+                            _this._viewer.utils[element.action]();
+                            _this._viewer.update();
+                        }
+                        element.node.rect.remove();
+                        element.node.text.remove();
+                    }
+                }
+                _this.showing = false;
+            };
+            var onMouseMove = function (event) {
+                if (_this.showing) {
+                    for (var i = 0; i < _this.elements.length; i++) {
+                        var element = _this.elements[i];
+                        if (element.text === "")
+                            continue;
+                        var x = _this._viewer.mousex;
+                        var y = _this._viewer.mousey;
+                        if (element.node.rect.isPointInside(x, y)) {
+                            element.node.rect.attr("fill", _this.overColor);
+                        }
+                        else {
+                            element.node.rect.attr("fill", _this.savedColor);
+                        }
+                    }
+                }
+            };
+            var onRightClick = function (event) {
+                var x = _this._viewer.mousex;
+                var y = _this._viewer.mousey;
+                _this._viewer.onClick(event);
+                var result = _this._viewer.traverseGraph(null, x, y, true);
+                if (result.hit) {
+                }
+                if (y + (ActionsBuilder.Viewer.NODE_HEIGHT * _this.elements.length) > _this._viewer.viewerElement.offsetHeight + _this._viewer.viewerElement.scrollTop) {
+                    y = (ActionsBuilder.Viewer.NODE_HEIGHT * _this.elements.length);
+                }
+                if (x + ActionsBuilder.Viewer.NODE_WIDTH > _this._viewer.viewerElement.offsetWidth + _this._viewer.viewerElement.scrollLeft) {
+                    x -= ActionsBuilder.Viewer.NODE_WIDTH;
+                }
+                if (!_this.showing) {
+                    if (_this._viewer.selectedNode === null)
+                        return;
+                    var yOffset = 10;
+                    for (var i = 0; i < _this.elements.length - 1; i++) {
+                        var element = _this.elements[i];
+                        element.node = _this._viewer._createNode(element.text, ActionsBuilder.Type.OBJECT, true);
+                        element.node.rect.attr("fill", Raphael.rgb(216, 216, 216));
+                        element.node.rect.attr("x", x);
+                        element.node.rect.attr("y", y + yOffset);
+                        element.node.text.attr("x", x + 5);
+                        element.node.text.attr("y", y + yOffset + element.node.rect.attr("height") / 2);
+                        yOffset += ActionsBuilder.Viewer.NODE_HEIGHT;
+                    }
+                    var separator = _this.elements[_this.elements.length - 1];
+                    separator.node = _this._viewer._createNode("", ActionsBuilder.Type.OBJECT, true);
+                    separator.node.rect.attr("fill", _this._viewer.getNodeColor(_this._viewer.selectedNode.type, _this._viewer.selectedNode.node.detached));
+                    separator.node.rect.attr("x", x);
+                    separator.node.rect.attr("y", y);
+                    separator.node.rect.attr("height", 10);
+                    _this.showing = true;
+                }
+                else {
+                    onClick(event);
+                    onRightClick(event);
+                }
+                window.event.returnValue = false;
+            };
+            document.addEventListener("click", onClick);
+            document.addEventListener("mousemove", onMouseMove);
+            element.addEventListener("contextmenu", onRightClick);
+        };
+        return ContextMenu;
+    })();
+    ActionsBuilder.ContextMenu = ContextMenu;
+})(ActionsBuilder || (ActionsBuilder = {}));

+ 148 - 148
Exporters/3ds Max/ActionsBuilder/actionsbuilder.contextMenu.ts

@@ -1,149 +1,149 @@
-module ActionsBuilder {
-
-    export interface ContextMenuElement {
-        text: string;
-        node: Node;
-        action: string;
-    }
-
-    export class ContextMenu {
-        public showing: boolean = false;
-        public savedColor: RaphaelColor = Raphael.rgb(255, 255, 255);
-        public overColor: RaphaelColor = Raphael.rgb(140, 200, 230);
-
-        private _viewer: Viewer = null;
-        private elements: Array<ContextMenuElement> = [
-            { text: "Reduce", node: null, action: "onReduce" },
-            { text: "Delete", node: null, action: "onRemoveNode" },
-            { text: "Delete branch", node: null, action: "onRemoveBranch" },
-            { text: "Connect / Disconnect", node: null, action: "onDetachAction" },
-            { text: "Copy", node: null, action: "onCopyStructure" },
-            { text: "Paste", node: null, action: "onPasteStructure" },
-            // Add other elements here
-            { text: "", node: null, action: null } // Color separator (top)
-        ];
-
-        /*
-        * Constructor
-        * @param viewer: the graph viewer
-        */
-        constructor(viewer: Viewer) {
-            // Members
-            this._viewer = viewer;
-
-            // Configure
-            this.attachControl(this._viewer.paper.canvas);
-        }
-
-        public attachControl(element: HTMLElement): void {
-            var onClick = (event: MouseEvent) => {
-                var x = this._viewer.mousex;
-                var y = this._viewer.mousey;
-
-                // Remove all context menu nodes, and run action if selected
-                if (this.showing) {
-                    for (var i = 0; i < this.elements.length; i++) {
-                        var element = this.elements[i];
-
-                        if (element.action && element.node.rect.isPointInside(x, y)) {
-                            this._viewer.utils[element.action]();
-                            this._viewer.update();
-                        }
-
-                        element.node.rect.remove();
-                        element.node.text.remove();
-                    }
-                }
-                this.showing = false;
-            };
-
-            var onMouseMove = (event: MouseEvent) => {
-                // Override context menu's node color if mouse is inside
-                if (this.showing) {
-                    for (var i = 0; i < this.elements.length; i++) {
-                        var element = this.elements[i];
-
-                        if (element.text === "")
-                            continue;
-
-                        var x = this._viewer.mousex;
-                        var y = this._viewer.mousey;
-
-                        if (element.node.rect.isPointInside(x, y)) {
-                            element.node.rect.attr("fill", this.overColor);
-                        }
-                        else {
-                            element.node.rect.attr("fill", this.savedColor);
-                        }
-                    }
-                }
-            };
-
-            var onRightClick = (event: MouseEvent) => {
-                var x = this._viewer.mousex;
-                var y = this._viewer.mousey;
-
-                this._viewer.onClick(event);
-
-                // Set selected node
-                var result = this._viewer.traverseGraph(null, x, y, true);
-                if (result.hit) {
-                    //this._viewer.selectedNode = result.element;
-                }
-
-                // Properly draw the context menu on the screen
-                if (y + (Viewer.NODE_HEIGHT * this.elements.length) > this._viewer.viewerElement.offsetHeight + this._viewer.viewerElement.scrollTop) {
-                    y = (Viewer.NODE_HEIGHT * this.elements.length);
-                }
-                if (x + Viewer.NODE_WIDTH > this._viewer.viewerElement.offsetWidth + this._viewer.viewerElement.scrollLeft) {
-                    x -= Viewer.NODE_WIDTH;
-                }
-
-                if (!this.showing) {
-                    if (this._viewer.selectedNode === null)
-                        return;
-
-                    // Create elements
-                    var yOffset = 10;
-
-                    for (var i = 0; i < this.elements.length - 1; i++) {
-                        var element = this.elements[i];
-
-                        element.node = this._viewer._createNode(element.text, Type.OBJECT, true);
-                        element.node.rect.attr("fill", Raphael.rgb(216, 216, 216));
-
-                        element.node.rect.attr("x", x);
-                        element.node.rect.attr("y", y + yOffset);
-
-                        element.node.text.attr("x", x + 5);
-                        element.node.text.attr("y", y + yOffset + element.node.rect.attr("height") / 2);
-
-                        yOffset += Viewer.NODE_HEIGHT;
-                    }
-
-                    // Color separator
-                    var separator = this.elements[this.elements.length - 1];
-                    separator.node = this._viewer._createNode("", Type.OBJECT, true);
-                    separator.node.rect.attr("fill", this._viewer.getNodeColor(this._viewer.selectedNode.type, this._viewer.selectedNode.node.detached));
-
-                    separator.node.rect.attr("x", x);
-                    separator.node.rect.attr("y", y);
-                    separator.node.rect.attr("height", 10);
-
-                    // Finish
-                    this.showing = true;
-                }
-                else {
-                    onClick(event);
-                    onRightClick(event);
-                }
-
-                window.event.returnValue = false;
-            };
-
-            document.addEventListener("click", onClick);
-            document.addEventListener("mousemove", onMouseMove);
-            element.addEventListener("contextmenu", onRightClick);
-        }
-    }
+module ActionsBuilder {
+
+    export interface ContextMenuElement {
+        text: string;
+        node: Node;
+        action: string;
+    }
+
+    export class ContextMenu {
+        public showing: boolean = false;
+        public savedColor: RaphaelColor = Raphael.rgb(255, 255, 255);
+        public overColor: RaphaelColor = Raphael.rgb(140, 200, 230);
+
+        private _viewer: Viewer = null;
+        private elements: Array<ContextMenuElement> = [
+            { text: "Reduce", node: null, action: "onReduce" },
+            { text: "Delete", node: null, action: "onRemoveNode" },
+            { text: "Delete branch", node: null, action: "onRemoveBranch" },
+            { text: "Connect / Disconnect", node: null, action: "onDetachAction" },
+            { text: "Copy", node: null, action: "onCopyStructure" },
+            { text: "Paste", node: null, action: "onPasteStructure" },
+            // Add other elements here
+            { text: "", node: null, action: null } // Color separator (top)
+        ];
+
+        /*
+        * Constructor
+        * @param viewer: the graph viewer
+        */
+        constructor(viewer: Viewer) {
+            // Members
+            this._viewer = viewer;
+
+            // Configure
+            this.attachControl(this._viewer.paper.canvas);
+        }
+
+        public attachControl(element: HTMLElement): void {
+            var onClick = (event: MouseEvent) => {
+                var x = this._viewer.mousex;
+                var y = this._viewer.mousey;
+
+                // Remove all context menu nodes, and run action if selected
+                if (this.showing) {
+                    for (var i = 0; i < this.elements.length; i++) {
+                        var element = this.elements[i];
+
+                        if (element.action && element.node.rect.isPointInside(x, y)) {
+                            this._viewer.utils[element.action]();
+                            this._viewer.update();
+                        }
+
+                        element.node.rect.remove();
+                        element.node.text.remove();
+                    }
+                }
+                this.showing = false;
+            };
+
+            var onMouseMove = (event: MouseEvent) => {
+                // Override context menu's node color if mouse is inside
+                if (this.showing) {
+                    for (var i = 0; i < this.elements.length; i++) {
+                        var element = this.elements[i];
+
+                        if (element.text === "")
+                            continue;
+
+                        var x = this._viewer.mousex;
+                        var y = this._viewer.mousey;
+
+                        if (element.node.rect.isPointInside(x, y)) {
+                            element.node.rect.attr("fill", this.overColor);
+                        }
+                        else {
+                            element.node.rect.attr("fill", this.savedColor);
+                        }
+                    }
+                }
+            };
+
+            var onRightClick = (event: MouseEvent) => {
+                var x = this._viewer.mousex;
+                var y = this._viewer.mousey;
+
+                this._viewer.onClick(event);
+
+                // Set selected node
+                var result = this._viewer.traverseGraph(null, x, y, true);
+                if (result.hit) {
+                    //this._viewer.selectedNode = result.element;
+                }
+
+                // Properly draw the context menu on the screen
+                if (y + (Viewer.NODE_HEIGHT * this.elements.length) > this._viewer.viewerElement.offsetHeight + this._viewer.viewerElement.scrollTop) {
+                    y = (Viewer.NODE_HEIGHT * this.elements.length);
+                }
+                if (x + Viewer.NODE_WIDTH > this._viewer.viewerElement.offsetWidth + this._viewer.viewerElement.scrollLeft) {
+                    x -= Viewer.NODE_WIDTH;
+                }
+
+                if (!this.showing) {
+                    if (this._viewer.selectedNode === null)
+                        return;
+
+                    // Create elements
+                    var yOffset = 10;
+
+                    for (var i = 0; i < this.elements.length - 1; i++) {
+                        var element = this.elements[i];
+
+                        element.node = this._viewer._createNode(element.text, Type.OBJECT, true);
+                        element.node.rect.attr("fill", Raphael.rgb(216, 216, 216));
+
+                        element.node.rect.attr("x", x);
+                        element.node.rect.attr("y", y + yOffset);
+
+                        element.node.text.attr("x", x + 5);
+                        element.node.text.attr("y", y + yOffset + element.node.rect.attr("height") / 2);
+
+                        yOffset += Viewer.NODE_HEIGHT;
+                    }
+
+                    // Color separator
+                    var separator = this.elements[this.elements.length - 1];
+                    separator.node = this._viewer._createNode("", Type.OBJECT, true);
+                    separator.node.rect.attr("fill", this._viewer.getNodeColor(this._viewer.selectedNode.type, this._viewer.selectedNode.node.detached));
+
+                    separator.node.rect.attr("x", x);
+                    separator.node.rect.attr("y", y);
+                    separator.node.rect.attr("height", 10);
+
+                    // Finish
+                    this.showing = true;
+                }
+                else {
+                    onClick(event);
+                    onRightClick(event);
+                }
+
+                window.event.returnValue = false;
+            };
+
+            document.addEventListener("click", onClick);
+            document.addEventListener("mousemove", onMouseMove);
+            element.addEventListener("contextmenu", onRightClick);
+        }
+    }
 } 

+ 316 - 0
Exporters/3ds Max/ActionsBuilder/actionsbuilder.js

@@ -0,0 +1,316 @@
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    var Type = (function () {
+        function Type() {
+        }
+        Object.defineProperty(Type, "TRIGGER", {
+            get: function () {
+                return Type._TRIGGER;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Type, "ACTION", {
+            get: function () {
+                return Type._ACTION;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Type, "FLOW_CONTROL", {
+            get: function () {
+                return Type._FLOW_CONTROL;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Type, "OBJECT", {
+            get: function () {
+                return Type._OBJECT;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Type, "SCENE", {
+            get: function () {
+                return Type._SCENE;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Type._TRIGGER = 0;
+        Type._ACTION = 1;
+        Type._FLOW_CONTROL = 2;
+        Type._OBJECT = 3;
+        Type._SCENE = 4;
+        return Type;
+    })();
+    ActionsBuilder.Type = Type;
+    var SceneElements = (function () {
+        function SceneElements() {
+        }
+        Object.defineProperty(SceneElements, "ENGINE", {
+            get: function () {
+                return SceneElements._ENGINE;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "SCENE", {
+            get: function () {
+                return SceneElements._SCENE;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "MESH", {
+            get: function () {
+                return SceneElements._MESH;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "LIGHT", {
+            get: function () {
+                return SceneElements._LIGHT;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "CAMERA", {
+            get: function () {
+                return SceneElements._CAMERA;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "MESHES", {
+            get: function () {
+                return SceneElements._MESHES;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "LIGHTS", {
+            get: function () {
+                return SceneElements._LIGHTS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "CAMERAS", {
+            get: function () {
+                return SceneElements._CAMERAS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "SOUNDS", {
+            get: function () {
+                return SceneElements._SOUNDS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "MESH_PROPERTIES", {
+            get: function () {
+                return SceneElements._MESH_PROPERTIES;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "LIGHT_PROPERTIES", {
+            get: function () {
+                return SceneElements._LIGHT_PROPERTIES;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "CAMERA_PROPERTIES", {
+            get: function () {
+                return SceneElements._CAMERA_PROPERTIES;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "SCENE_PROPERTIES", {
+            get: function () {
+                return SceneElements._SCENE_PROPERTIES;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "TYPES", {
+            get: function () {
+                return SceneElements._TYPES;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneElements, "OPERATORS", {
+            get: function () {
+                return SceneElements._OPERATORS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        SceneElements.GetInstanceOf = function (object) {
+            if (object === null || object === undefined) {
+                return "";
+            }
+            return object.constructor.toString().match(/function (\w*)/)[1];
+        };
+        SceneElements.TestInstanceOf = function (object, propertyName) {
+            if (object === null || object.constructor === null) {
+                return false;
+            }
+            if (propertyName.length > 0 && propertyName[0] === "_")
+                return false;
+            var name = SceneElements.GetInstanceOf(object);
+            for (var i = 0; i < SceneElements.TYPES.length; i++) {
+                if (name === SceneElements.TYPES[i]) {
+                    return true;
+                }
+            }
+            return false;
+        };
+        SceneElements._ENGINE = new BABYLON.Engine(document.getElementById("RenderCanvasID"));
+        SceneElements._SCENE = new BABYLON.Scene(SceneElements.ENGINE);
+        SceneElements._MESH = new BABYLON.Mesh("mesh", SceneElements._SCENE);
+        SceneElements._LIGHT = new BABYLON.Light("light", SceneElements._SCENE);
+        SceneElements._CAMERA = new BABYLON.Camera("camera", BABYLON.Vector3.Zero(), SceneElements._SCENE);
+        SceneElements._MESHES = new Array();
+        SceneElements._LIGHTS = new Array();
+        SceneElements._CAMERAS = new Array();
+        SceneElements._SOUNDS = new Array();
+        SceneElements._MESH_PROPERTIES = new Array();
+        SceneElements._LIGHT_PROPERTIES = new Array();
+        SceneElements._CAMERA_PROPERTIES = new Array();
+        SceneElements._SCENE_PROPERTIES = new Array();
+        SceneElements._TYPES = new Array();
+        SceneElements._OPERATORS = new Array();
+        return SceneElements;
+    })();
+    ActionsBuilder.SceneElements = SceneElements;
+    var specialTypes = [
+        "StandardMaterial"
+    ];
+    SceneElements.MESH.material = new BABYLON.StandardMaterial("material", SceneElements.SCENE);
+    var addSpecialType = function (object, properties, thing) {
+        for (var specialThing in object[thing]) {
+            if (object[thing].hasOwnProperty(specialThing) && SceneElements.TestInstanceOf(object[thing][specialThing], specialThing)) {
+                properties.push(thing + "." + specialThing);
+            }
+        }
+    };
+    SceneElements.TYPES.push("Color3");
+    SceneElements.TYPES.push("Boolean");
+    SceneElements.TYPES.push("Number");
+    SceneElements.TYPES.push("Vector2");
+    SceneElements.TYPES.push("Vector3");
+    SceneElements.TYPES.push("String");
+    SceneElements.OPERATORS.push("IsEqual");
+    SceneElements.OPERATORS.push("IsDifferent");
+    SceneElements.OPERATORS.push("IsGreater");
+    SceneElements.OPERATORS.push("IsLesser");
+    for (var thing in SceneElements.MESH) {
+        var instance = SceneElements.GetInstanceOf(SceneElements.MESH[thing]);
+        if (SceneElements.MESH.hasOwnProperty(thing)) {
+            if (specialTypes.indexOf(instance) !== -1) {
+                addSpecialType(SceneElements.MESH, SceneElements.MESH_PROPERTIES, thing);
+            }
+            else if (SceneElements.TestInstanceOf(SceneElements.MESH[thing], thing)) {
+                SceneElements.MESH_PROPERTIES.push(thing);
+            }
+        }
+    }
+    for (var thing in SceneElements.LIGHT) {
+        if (SceneElements.LIGHT.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.LIGHT[thing], thing)) {
+            SceneElements.LIGHT_PROPERTIES.push(thing);
+        }
+    }
+    for (var thing in SceneElements.CAMERA) {
+        if (SceneElements.CAMERA.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.CAMERA[thing], thing)) {
+            SceneElements.CAMERA_PROPERTIES.push(thing);
+        }
+    }
+    for (var thing in SceneElements.SCENE) {
+        if (SceneElements.SCENE.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.SCENE[thing], thing)) {
+            SceneElements.SCENE_PROPERTIES.push(thing);
+        }
+    }
+    var Elements = (function () {
+        function Elements() {
+        }
+        Object.defineProperty(Elements, "TRIGGERS", {
+            get: function () {
+                return Elements._TRIGGERS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Elements, "ACTIONS", {
+            get: function () {
+                return Elements._ACTIONS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Elements, "FLOW_CONTROLS", {
+            get: function () {
+                return Elements._FLOW_CONTROLS;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Elements.GetElementFromName = function (name) {
+            for (var i = 0; i < Elements.TRIGGERS.length; i++) {
+                if (Elements.TRIGGERS[i].name === name) {
+                    return Elements._TRIGGERS[i];
+                }
+            }
+            for (var i = 0; i < Elements.ACTIONS.length; i++) {
+                if (Elements.ACTIONS[i].name === name) {
+                    return Elements._ACTIONS[i];
+                }
+            }
+            for (var i = 0; i < Elements.FLOW_CONTROLS.length; i++) {
+                if (Elements.FLOW_CONTROLS[i].name === name) {
+                    return Elements._FLOW_CONTROLS[i];
+                }
+            }
+            return null;
+        };
+        Elements._TRIGGERS = new Array();
+        Elements._ACTIONS = new Array();
+        Elements._FLOW_CONTROLS = new Array();
+        return Elements;
+    })();
+    ActionsBuilder.Elements = Elements;
+    Elements.TRIGGERS.push({ name: "OnPickTrigger", text: "pick", properties: [], description: "When the user picks the edited mesh" });
+    Elements.TRIGGERS.push({ name: "OnLeftPickTrigger", text: "left pick", properties: [], description: "When the user picks the edited mesh using the left click" });
+    Elements.TRIGGERS.push({ name: "OnRightPickTrigger", text: "right pick", properties: [], description: "When the user picks the edited mesh using the right click" });
+    Elements.TRIGGERS.push({ name: "OnCenterPickTrigger", text: "center pick", properties: [], description: "When the user picks the edited mesh using the click of the mouse wheel" });
+    Elements.TRIGGERS.push({ name: "OnPointerOverTrigger", text: "pointer over", properties: [], description: "When the user's mouse is over the edited mesh" });
+    Elements.TRIGGERS.push({ name: "OnPointerOutTrigger", text: "pointer out", properties: [], description: "When the user's mouse is out of the edited mesh" });
+    Elements.TRIGGERS.push({ name: "OnEveryFrameTrigger", text: "every frame", properties: [], description: "This trigger is called each frame (only on scene)" });
+    Elements.TRIGGERS.push({ name: "OnIntersectionEnterTrigger", text: "intersection enter", properties: [{ targetType: "MeshProperties", text: "parameter", value: "Object name?" }], description: "When the edited mesh intersects the another mesh predefined in the options" });
+    Elements.TRIGGERS.push({ name: "OnIntersectionExitTrigger", text: "intersection exit", properties: [{ targetType: "MeshProperties", text: "parameter", value: "Object name?" }], description: "When the edited mesh exits intersection with the another mesh predefined in the options" });
+    Elements.TRIGGERS.push({ name: "OnKeyDownTrigger", text: "key down", properties: [{ targetType: null, text: "parameter:", value: "a" }], description: "When the user pressed a key (enter the key character, example: \"r\")" });
+    Elements.TRIGGERS.push({ name: "OnKeyUpTrigger", text: "key up", properties: [{ targetType: null, text: "parameter:", value: "a" }], description: "When the user unpressed a key (enter the key character, example: \"p\")" });
+    Elements.ACTIONS.push({ name: "SwitchBooleanAction", text: "switch boolean", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }], description: "Switches the boolean value of a given parameter of the target object: true to false, or false to true" });
+    Elements.ACTIONS.push({ name: "SetStateAction", text: "set state", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "value", value: "" }], description: "Sets a new state value for the target object (example: \"off\" or \"on\")" });
+    Elements.ACTIONS.push({ name: "SetValueAction", text: "set value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }], description: "Sets a new value to the specified parameter of the target object (example: position.x to 0.0)" });
+    Elements.ACTIONS.push({ name: "SetParentAction", text: "set parent", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "parent", value: "" }], description: "Sets the new parent of the target object (example: a mesh or a light)" });
+    Elements.ACTIONS.push({ name: "IncrementValueAction", text: "increment value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }], description: "Increments the value of the given parameter of the target object. The value can be negative. (example: increment position.x of 5.0)" });
+    Elements.ACTIONS.push({ name: "PlayAnimationAction", text: "play animation", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "from", value: "0" }, { text: "to", value: "150" }, { text: "loop", value: "false" }], description: "Plays an animation of the target object. Specify the start frame, the end frame and if the animation should loop." });
+    Elements.ACTIONS.push({ name: "StopAnimationAction", text: "stop animation", properties: [{ targetType: "MeshProperties", text: "target", value: "" }], description: "Stops the animations of the target object." });
+    Elements.ACTIONS.push({ name: "DoNothingAction", text: "do nothing", properties: [], description: "Does nothing, can be used to balance/equilibrate the actions graph." });
+    Elements.ACTIONS.push({ name: "InterpolateValueAction", text: "interpolate value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "0" }, { text: "duration", value: "1000" }, { text: "stopOtherAnimations", value: "false" }], description: "Creates an animation (key frames) that animates the target object by interpolating the given parameter of the target value." });
+    Elements.ACTIONS.push({ name: "PlaySoundAction", text: "play sound", properties: [{ text: "sound", value: "" }], description: "Plays the specified sound." });
+    Elements.ACTIONS.push({ name: "StopSoundAction", text: "stop sound", properties: [{ text: "sound", value: "" }], description: "Stops the specified sound." });
+    Elements.ACTIONS.push({ name: "CombineAction", text: "combine", properties: [], description: "Special action that combines multiple actions. The combined actions are executed at the same time. Drag'n'drop the new actions inside to combine actions." });
+    Elements.FLOW_CONTROLS.push({ name: "ValueCondition", text: "value condition", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }, { text: "operator", value: SceneElements.OPERATORS[0] }], description: "A condition checking if a given value is equal, different, lesser or greater than the given parameter of the target object" });
+    Elements.FLOW_CONTROLS.push({ name: "StateCondition", text: "state condition", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "value", value: "" }], description: "A condition checking if the target object's state is equal to the given state. See \"set state\" action to set a state to an object." });
+    Elements.FLOW_CONTROLS.push({ name: "Hub", text: "hub", properties: [], description: "The hub is internally used by the Combine Action. It allows to add children to the Combine Action" });
+})(ActionsBuilder || (ActionsBuilder = {}));

+ 209 - 0
Exporters/3ds Max/ActionsBuilder/actionsbuilder.list.js

@@ -0,0 +1,209 @@
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    var ListElement = (function () {
+        function ListElement() {
+            this.rect = null;
+            this.text = null;
+            this.name = "";
+            this.type = ActionsBuilder.Type.TRIGGER;
+            this.element = null;
+        }
+        return ListElement;
+    })();
+    ActionsBuilder.ListElement = ListElement;
+    var List = (function () {
+        function List(viewer) {
+            var _this = this;
+            this._listElements = new Array();
+            this.listElement = document.getElementById("ListsElementID");
+            this.triggersElement = document.getElementById("TriggersListID");
+            this.actionsElement = document.getElementById("ActionsListID");
+            this.flowControlsElement = document.getElementById("FlowActionsListID");
+            this._parentContainer = document.getElementById("ParentContainerID");
+            this._viewer = viewer;
+            this.triggersList = Raphael("TriggersListID", (25 * screen.width) / 100, 400);
+            this.actionsList = Raphael("ActionsListID", (25 * screen.width) / 100, 400);
+            this.flowControlsList = Raphael("FlowActionsListID", (25 * screen.width) / 100, 400);
+            window.addEventListener("resize", function (event) {
+                _this.onResize(event);
+            });
+        }
+        Object.defineProperty(List, "ELEMENT_HEIGHT", {
+            get: function () {
+                return 25;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        List.prototype.onResize = function (event) {
+            var tools = document.getElementById("ToolsButtonsID");
+            this.listElement.style.height = window.innerHeight - tools.getBoundingClientRect().height - 25 + "px";
+            var listElementWidth = this.listElement.getBoundingClientRect().width;
+            for (var i = 0; i < this._listElements.length; i++) {
+                var rect = this._listElements[i].rect;
+                rect.attr("width", listElementWidth - 40);
+            }
+            this.triggersList.setSize(listElementWidth, this.triggersList.height);
+            this.actionsList.setSize(listElementWidth, this.triggersList.height);
+            this.flowControlsList.setSize(listElementWidth, this.triggersList.height);
+        };
+        List.prototype.createListsElements = function () {
+            var excludedTriggers = [6, 9, 10];
+            var yPosition = 10;
+            var textColor = Raphael.rgb(61, 72, 76);
+            var whiteColor = Raphael.rgb(255, 255, 255);
+            var configureTitle = function (listElement, rectColor) {
+                listElement.text.attr("x", 15);
+                listElement.rect.attr("fill", rectColor);
+                listElement.text.attr("font-family", "Sinkin Sans Medium");
+                listElement.text.attr("font-size", "11");
+            };
+            var triggers = this._createListElement(this.triggersList, yPosition, "TRIGGERS", ActionsBuilder.Type.TRIGGER, whiteColor, false);
+            yPosition += List.ELEMENT_HEIGHT;
+            configureTitle(triggers, Raphael.rgb(41, 129, 255));
+            for (var i = 0; i < ActionsBuilder.Elements.TRIGGERS.length; i++) {
+                var element = ActionsBuilder.Elements.TRIGGERS[i];
+                if (this._viewer.root.type === ActionsBuilder.Type.OBJECT && excludedTriggers.indexOf(i) !== -1) {
+                    continue;
+                }
+                else if (this._viewer.root.type === ActionsBuilder.Type.SCENE && excludedTriggers.indexOf(i) === -1) {
+                    continue;
+                }
+                var trigger = this._createListElement(this.triggersList, yPosition, element.text, ActionsBuilder.Type.TRIGGER, textColor, true, element);
+                trigger.rect.attr("fill", Raphael.rgb(133, 154, 185));
+                yPosition += List.ELEMENT_HEIGHT;
+            }
+            yPosition += List.ELEMENT_HEIGHT;
+            this.triggersElement.style.height = this.triggersList.canvas.style.height = yPosition + "px";
+            this._createCollapseAnimation(this.triggersList, this.triggersElement, triggers, yPosition);
+            yPosition = 10;
+            var actions = this._createListElement(this.actionsList, yPosition, "ACTIONS", ActionsBuilder.Type.ACTION, textColor, false);
+            yPosition += List.ELEMENT_HEIGHT;
+            configureTitle(actions, Raphael.rgb(255, 220, 42));
+            for (var i = 0; i < ActionsBuilder.Elements.ACTIONS.length; i++) {
+                var element = ActionsBuilder.Elements.ACTIONS[i];
+                var action = this._createListElement(this.actionsList, yPosition, element.text, ActionsBuilder.Type.ACTION, textColor, true, element);
+                action.rect.attr("fill", Raphael.rgb(182, 185, 132));
+                yPosition += List.ELEMENT_HEIGHT;
+            }
+            yPosition += List.ELEMENT_HEIGHT;
+            this.actionsElement.style.height = this.actionsList.canvas.style.height = yPosition + "px";
+            this._createCollapseAnimation(this.actionsList, this.actionsElement, actions, yPosition);
+            yPosition = 10;
+            var flowControls = this._createListElement(this.flowControlsList, yPosition, "FLOW CONTROLS", ActionsBuilder.Type.FLOW_CONTROL, whiteColor, false);
+            yPosition += List.ELEMENT_HEIGHT;
+            configureTitle(flowControls, Raphael.rgb(255, 41, 53));
+            for (var i = 0; i < ActionsBuilder.Elements.FLOW_CONTROLS.length - 1; i++) {
+                var element = ActionsBuilder.Elements.FLOW_CONTROLS[i];
+                var flowControl = this._createListElement(this.flowControlsList, yPosition, element.text, ActionsBuilder.Type.FLOW_CONTROL, textColor, true, element);
+                flowControl.rect.attr("fill", Raphael.rgb(185, 132, 140));
+                yPosition += List.ELEMENT_HEIGHT;
+            }
+            yPosition += List.ELEMENT_HEIGHT;
+            this.flowControlsElement.style.height = this.flowControlsList.canvas.style.height = yPosition + "px";
+            this._createCollapseAnimation(this.flowControlsList, this.flowControlsElement, flowControls, yPosition);
+        };
+        List.prototype.clearLists = function () {
+            for (var i = 0; i < this._listElements.length; i++) {
+                this._removeListElement(this._listElements[i]);
+            }
+            this._listElements.splice(0, this._listElements.length - 1);
+        };
+        List.prototype.setColorTheme = function (color) {
+            this.triggersList.canvas.style.backgroundColor = color;
+            this.actionsList.canvas.style.backgroundColor = color;
+            this.flowControlsList.canvas.style.backgroundColor = color;
+        };
+        List.prototype._createListElement = function (paper, yPosition, text, type, textColor, drag, element) {
+            var object = new ListElement();
+            object.rect = paper.rect(10, yPosition, 300, List.ELEMENT_HEIGHT);
+            object.text = paper.text(30, yPosition + object.rect.attr("height") / 2, text);
+            object.text.attr("fill", textColor);
+            object.text.attr("text-anchor", "start");
+            object.text.attr("font-size", "12");
+            object.text.attr("text-anchor", "start");
+            object.text.attr("font-family", "Sinkin Sans Light");
+            if (drag) {
+                this._createListElementAnimation(object);
+            }
+            object.type = type;
+            object.element = element;
+            this._listElements.push(object);
+            return object;
+        };
+        List.prototype._removeListElement = function (element) {
+            element.rect.remove();
+            element.text.remove();
+        };
+        List.prototype._createCollapseAnimation = function (paper, htmlElement, element, expandedHeight) {
+            var onClick = function (event) {
+                var height = htmlElement.style.height;
+                if (height === expandedHeight + "px") {
+                    htmlElement.style.height = paper.canvas.style.height = 35 + "px";
+                }
+                else {
+                    htmlElement.style.height = paper.canvas.style.height = expandedHeight + "px";
+                }
+            };
+            element.rect.click(onClick);
+        };
+        List.prototype._createListElementAnimation = function (element) {
+            var _this = this;
+            var onMove = function (dx, dy, x, y) { };
+            var onStart = function (x, y, event) {
+                _this._parentContainer.style.cursor = "copy";
+                element.rect.animate({
+                    x: -10,
+                    opacity: 0.25
+                }, 500, ">");
+                element.text.animate({
+                    x: 10,
+                    opacity: 0.25
+                }, 500, ">");
+            };
+            var onEnd = function (event) {
+                _this._parentContainer.style.cursor = "default";
+                element.rect.animate({
+                    x: 10,
+                    opacity: 1.0
+                }, 500, "<");
+                element.text.animate({
+                    x: 30,
+                    opacity: 1.0
+                }, 500, "<");
+                var dragResult = _this._viewer.traverseGraph(null, _this._viewer.mousex, _this._viewer.mousey, false);
+                if (dragResult.hit) {
+                    if (element.type === ActionsBuilder.Type.TRIGGER && dragResult.action !== _this._viewer.root) {
+                        alert("Triggers can be dragged only on the root node (the mesh)");
+                        return;
+                    }
+                    if (element.type === ActionsBuilder.Type.ACTION && dragResult.action === _this._viewer.root) {
+                        alert("Please add a trigger before.");
+                        return;
+                    }
+                    if (element.type === ActionsBuilder.Type.FLOW_CONTROL && dragResult.action === _this._viewer.root) {
+                        return;
+                    }
+                    if (element.type === ActionsBuilder.Type.FLOW_CONTROL && dragResult.action.combineArray !== null) {
+                        alert("A condition cannot be handled by a Combine Action.");
+                        return;
+                    }
+                    if ((element.type === ActionsBuilder.Type.FLOW_CONTROL || element.type === ActionsBuilder.Type.ACTION) && dragResult.action.type === ActionsBuilder.Type.TRIGGER && dragResult.action.children.length > 0) {
+                        alert("Triggers can have only one child. Please add another trigger of same type.");
+                        return;
+                    }
+                    if (!(dragResult.action.combineArray !== null) && dragResult.action.children.length > 0 && dragResult.action.type !== ActionsBuilder.Type.TRIGGER && dragResult.action !== _this._viewer.root) {
+                        alert("An action can have only one child.");
+                        return;
+                    }
+                    _this._viewer.addAction(dragResult.action, element.type, element.element);
+                    _this._viewer.update();
+                }
+            };
+            element.rect.drag(onMove, onStart, onEnd);
+            element.text.drag(onMove, onStart, onEnd);
+        };
+        return List;
+    })();
+    ActionsBuilder.List = List;
+})(ActionsBuilder || (ActionsBuilder = {}));

+ 305 - 305
Exporters/3ds Max/ActionsBuilder/actionsbuilder.list.ts

@@ -1,306 +1,306 @@
-module ActionsBuilder {
-    export class ListElement {
-        public rect: Rect = null;
-        public text: Text = null;
-        public name: string = "";
-        public type: number = Type.TRIGGER;
-        public element: Element = null;
-    }
-
-    export class List {
-        public listElement: HTMLElement;
-        public triggersElement: HTMLElement;
-        public actionsElement: HTMLElement;
-        public flowControlsElement: HTMLElement;
-
-        public triggersList: Paper;
-        public actionsList: Paper;
-        public flowControlsList: Paper;
-
-        private _parentContainer: HTMLElement;
-        private _listElements: Array<ListElement> = new Array<ListElement>();
-        private _viewer: Viewer;
-
-        public static get ELEMENT_HEIGHT(): number {
-            return 25;
-        }
-
-        /**
-        * Constructor
-        */
-        constructor(viewer: Viewer) {
-            // Get HTML elements
-            this.listElement = document.getElementById("ListsElementID");
-            this.triggersElement = document.getElementById("TriggersListID");
-            this.actionsElement = document.getElementById("ActionsListID");
-            this.flowControlsElement = document.getElementById("FlowActionsListID");
-            this._parentContainer = document.getElementById("ParentContainerID");
-
-            // Configure this
-            this._viewer = viewer;
-
-            // Create elements (lists)
-            this.triggersList = Raphael("TriggersListID", (25 * screen.width) / 100, 400);
-            this.actionsList = Raphael("ActionsListID", (25 * screen.width) / 100, 400);
-            this.flowControlsList = Raphael("FlowActionsListID", (25 * screen.width) / 100, 400);
-
-            // Manage events
-            window.addEventListener("resize", (event: Event) => {
-                this.onResize(event);
-            });
-        }
-
-        /**
-        * Resize event that resizes the list element dynamically
-        * @param event: the resize event
-        */
-        public onResize(event?: Event): void {
-            var tools = document.getElementById("ToolsButtonsID");
-            this.listElement.style.height = window.innerHeight - tools.getBoundingClientRect().height - 25 + "px";
-
-            var listElementWidth = this.listElement.getBoundingClientRect().width;
-            for (var i = 0; i < this._listElements.length; i++) {
-                var rect = this._listElements[i].rect;
-                rect.attr("width", listElementWidth - 40);
-            }
-
-            this.triggersList.setSize(listElementWidth, this.triggersList.height);
-            this.actionsList.setSize(listElementWidth, this.triggersList.height);
-            this.flowControlsList.setSize(listElementWidth, this.triggersList.height);
-
-        }
-
-        public createListsElements(): void {
-            var excludedTriggers = [6, 9, 10];
-            var yPosition = 10;
-            var textColor = Raphael.rgb(61, 72, 76);
-            var whiteColor = Raphael.rgb(255, 255, 255);
-
-            var configureTitle = (listElement: ListElement, rectColor: RaphaelColor) => {
-                listElement.text.attr("x", 15);
-                listElement.rect.attr("fill", rectColor);
-                listElement.text.attr("font-family", "Sinkin Sans Medium");
-                listElement.text.attr("font-size", "11");
-            };
-
-            // Create triggers
-            var triggers = this._createListElement(this.triggersList, yPosition, "TRIGGERS", Type.TRIGGER, whiteColor, false);
-            yPosition += List.ELEMENT_HEIGHT;
-            configureTitle(triggers, Raphael.rgb(41, 129, 255));
-
-            for (var i = 0; i < Elements.TRIGGERS.length; i++) {
-                var element: any = Elements.TRIGGERS[i];
-
-                if (this._viewer.root.type === Type.OBJECT && excludedTriggers.indexOf(i) !== -1) {
-                    continue;
-                }
-                else if (this._viewer.root.type === Type.SCENE && excludedTriggers.indexOf(i) === -1) {
-                    continue;
-                }
-
-                var trigger = this._createListElement(this.triggersList, yPosition, element.text, Type.TRIGGER, textColor, true, element);
-
-                trigger.rect.attr("fill", Raphael.rgb(133, 154, 185));
-                yPosition += List.ELEMENT_HEIGHT;
-            }
-
-            yPosition += List.ELEMENT_HEIGHT;
-            this.triggersElement.style.height = this.triggersList.canvas.style.height = yPosition + "px";
-            this._createCollapseAnimation(this.triggersList, this.triggersElement, triggers, yPosition);
-
-            // Create actions
-            yPosition = 10;
-            var actions = this._createListElement(this.actionsList, yPosition, "ACTIONS", Type.ACTION, textColor, false);
-            yPosition += List.ELEMENT_HEIGHT;
-            configureTitle(actions, Raphael.rgb(255, 220, 42));
-
-            for (var i = 0; i < Elements.ACTIONS.length; i++) {
-                var element: any = Elements.ACTIONS[i];
-                var action = this._createListElement(this.actionsList, yPosition, element.text, Type.ACTION, textColor, true, element);
-
-                action.rect.attr("fill", Raphael.rgb(182, 185, 132));
-                yPosition += List.ELEMENT_HEIGHT;
-            }
-
-            yPosition += List.ELEMENT_HEIGHT;
-            this.actionsElement.style.height = this.actionsList.canvas.style.height = yPosition + "px";
-            this._createCollapseAnimation(this.actionsList, this.actionsElement, actions, yPosition);
-
-            // Create flow controls
-            yPosition = 10;
-            var flowControls = this._createListElement(this.flowControlsList, yPosition, "FLOW CONTROLS", Type.FLOW_CONTROL, whiteColor, false);
-            yPosition += List.ELEMENT_HEIGHT;
-            configureTitle(flowControls, Raphael.rgb(255, 41, 53));
-
-            for (var i = 0; i < Elements.FLOW_CONTROLS.length - 1; i++) {
-                var element: any = Elements.FLOW_CONTROLS[i];
-                var flowControl = this._createListElement(this.flowControlsList, yPosition, element.text, Type.FLOW_CONTROL, textColor, true, element);
-
-                flowControl.rect.attr("fill", Raphael.rgb(185, 132, 140));
-                yPosition += List.ELEMENT_HEIGHT;
-            }
-
-            yPosition += List.ELEMENT_HEIGHT;
-            this.flowControlsElement.style.height = this.flowControlsList.canvas.style.height = yPosition + "px";
-            this._createCollapseAnimation(this.flowControlsList, this.flowControlsElement, flowControls, yPosition);
-        }
-
-        /**
-        * Clears the list of elements and removes the elements
-        */
-        public clearLists(): void {
-            for (var i = 0; i < this._listElements.length; i++) {
-                this._removeListElement(this._listElements[i]);
-            }
-            this._listElements.splice(0, this._listElements.length - 1);
-        }
-
-        /**
-        * Sets the color theme of the lists
-        * @param color: the theme color
-        */
-        public setColorTheme(color: string): void {
-            this.triggersList.canvas.style.backgroundColor = color;
-            this.actionsList.canvas.style.backgroundColor = color;
-            this.flowControlsList.canvas.style.backgroundColor = color;
-        }
-
-        /**
-        * Creates a list element
-        * @param paper: the Raphael.js paper
-        * @param yPosition: the y position of the element
-        * @param text: the element text
-        * @param type: the element type (trigger, action, flow control)
-        * @param textColor: the text color
-        * @param drag: if the element should be drag'n'dropped
-        */
-        private _createListElement(paper: Paper, yPosition: number, text: string, type: number,
-                                   textColor: RaphaelColor, drag: boolean, element?: Element): ListElement
-        {
-            var object = new ListElement();
-
-            object.rect = paper.rect(10, yPosition, 300, List.ELEMENT_HEIGHT);
-
-            object.text = paper.text(30, yPosition + object.rect.attr("height") / 2, text);
-            object.text.attr("fill", textColor);
-            object.text.attr("text-anchor", "start");
-            object.text.attr("font-size", "12");
-            object.text.attr("text-anchor", "start");
-            object.text.attr("font-family", "Sinkin Sans Light");
-
-            if (drag) {
-                this._createListElementAnimation(object);
-            }
-
-            object.type = type;
-            object.element = element;
-
-            this._listElements.push(object);
-            return object;
-        }
-
-        /**
-        * Removes a list element
-        * @param element: the element to remove
-        */
-        private _removeListElement(element: ListElement): void {
-            element.rect.remove();
-            element.text.remove();
-        }
-
-        /*
-        * Creates the collapse animation of a list
-        * @param paper: the list paper
-        * @param htmlElement: the list div container
-        * @param element: the list element to click on
-        * @param expandedHeight: the height when the list is expanded
-        */
-        private _createCollapseAnimation(paper: Paper, htmlElement: HTMLElement, element: ListElement, expandedHeight: number): void {
-            var onClick = (event: MouseEvent) => {
-                var height = htmlElement.style.height;
-                if (height === expandedHeight + "px") {
-                    htmlElement.style.height = paper.canvas.style.height = 35 + "px";
-                }
-                else {
-                    htmlElement.style.height = paper.canvas.style.height = expandedHeight + "px";
-                }
-            };
-
-            element.rect.click(onClick);
-        }
-
-        /*
-        * Creates the animation of a list element
-        * @param element: the list element to animate
-        */
-        private _createListElementAnimation(element: ListElement): void {
-            var onMove = (dx: number, dy: number, x: number, y: number) =>
-            { };
-
-            var onStart = (x: number, y: number, event: MouseEvent) => {
-                this._parentContainer.style.cursor = "copy";
-                element.rect.animate({
-                    x: -10,
-                    opacity: 0.25
-                }, 500, ">");
-                element.text.animate({
-                    x: 10,
-                    opacity: 0.25
-                }, 500, ">");
-            };
-
-            var onEnd = (event: MouseEvent) => {
-                this._parentContainer.style.cursor = "default";
-                element.rect.animate({
-                    x: 10,
-                    opacity: 1.0
-                }, 500, "<");
-                element.text.animate({
-                    x: 30,
-                    opacity: 1.0
-                }, 500, "<");
-
-                var dragResult = this._viewer.traverseGraph(null, this._viewer.mousex, this._viewer.mousey, false);
-
-                if (dragResult.hit) {
-                    if (element.type === Type.TRIGGER && dragResult.action !== this._viewer.root) {
-                        alert("Triggers can be dragged only on the root node (the mesh)");
-                        return;
-                    }
-
-                    if (element.type === Type.ACTION && dragResult.action === this._viewer.root) {
-                        alert("Please add a trigger before.");
-                        return;
-                    }
-
-                    //if (element.type === Type.FLOW_CONTROL && (dragResult.action === this._viewer.root || (dragResult.action.type === Type.FLOW_CONTROL && dragResult.action.parent.hub === null))) {
-                    if (element.type === Type.FLOW_CONTROL && dragResult.action === this._viewer.root) {
-                        return;
-                    }
-
-                    if (element.type === Type.FLOW_CONTROL && dragResult.action.combineArray !== null) {
-                        alert("A condition cannot be handled by a Combine Action.");
-                        return;
-                    }
-
-                    if ((element.type === Type.FLOW_CONTROL || element.type === Type.ACTION) && dragResult.action.type === Type.TRIGGER && dragResult.action.children.length > 0) {
-                        alert("Triggers can have only one child. Please add another trigger of same type.");
-                        return;
-                    }
-
-                    if (!(dragResult.action.combineArray !== null) && dragResult.action.children.length > 0 && dragResult.action.type !== Type.TRIGGER && dragResult.action !== this._viewer.root) {
-                        alert("An action can have only one child.");
-                        return;
-                    }
-
-                    this._viewer.addAction(dragResult.action, element.type, element.element);
-                    this._viewer.update();
-                }
-            };
-
-            element.rect.drag(onMove, onStart, onEnd);
-            element.text.drag(onMove, onStart, onEnd);
-        }
-
-    }
+module ActionsBuilder {
+    export class ListElement {
+        public rect: Rect = null;
+        public text: Text = null;
+        public name: string = "";
+        public type: number = Type.TRIGGER;
+        public element: Element = null;
+    }
+
+    export class List {
+        public listElement: HTMLElement;
+        public triggersElement: HTMLElement;
+        public actionsElement: HTMLElement;
+        public flowControlsElement: HTMLElement;
+
+        public triggersList: Paper;
+        public actionsList: Paper;
+        public flowControlsList: Paper;
+
+        private _parentContainer: HTMLElement;
+        private _listElements: Array<ListElement> = new Array<ListElement>();
+        private _viewer: Viewer;
+
+        public static get ELEMENT_HEIGHT(): number {
+            return 25;
+        }
+
+        /**
+        * Constructor
+        */
+        constructor(viewer: Viewer) {
+            // Get HTML elements
+            this.listElement = document.getElementById("ListsElementID");
+            this.triggersElement = document.getElementById("TriggersListID");
+            this.actionsElement = document.getElementById("ActionsListID");
+            this.flowControlsElement = document.getElementById("FlowActionsListID");
+            this._parentContainer = document.getElementById("ParentContainerID");
+
+            // Configure this
+            this._viewer = viewer;
+
+            // Create elements (lists)
+            this.triggersList = Raphael("TriggersListID", (25 * screen.width) / 100, 400);
+            this.actionsList = Raphael("ActionsListID", (25 * screen.width) / 100, 400);
+            this.flowControlsList = Raphael("FlowActionsListID", (25 * screen.width) / 100, 400);
+
+            // Manage events
+            window.addEventListener("resize", (event: Event) => {
+                this.onResize(event);
+            });
+        }
+
+        /**
+        * Resize event that resizes the list element dynamically
+        * @param event: the resize event
+        */
+        public onResize(event?: Event): void {
+            var tools = document.getElementById("ToolsButtonsID");
+            this.listElement.style.height = window.innerHeight - tools.getBoundingClientRect().height - 25 + "px";
+
+            var listElementWidth = this.listElement.getBoundingClientRect().width;
+            for (var i = 0; i < this._listElements.length; i++) {
+                var rect = this._listElements[i].rect;
+                rect.attr("width", listElementWidth - 40);
+            }
+
+            this.triggersList.setSize(listElementWidth, this.triggersList.height);
+            this.actionsList.setSize(listElementWidth, this.triggersList.height);
+            this.flowControlsList.setSize(listElementWidth, this.triggersList.height);
+
+        }
+
+        public createListsElements(): void {
+            var excludedTriggers = [6, 9, 10];
+            var yPosition = 10;
+            var textColor = Raphael.rgb(61, 72, 76);
+            var whiteColor = Raphael.rgb(255, 255, 255);
+
+            var configureTitle = (listElement: ListElement, rectColor: RaphaelColor) => {
+                listElement.text.attr("x", 15);
+                listElement.rect.attr("fill", rectColor);
+                listElement.text.attr("font-family", "Sinkin Sans Medium");
+                listElement.text.attr("font-size", "11");
+            };
+
+            // Create triggers
+            var triggers = this._createListElement(this.triggersList, yPosition, "TRIGGERS", Type.TRIGGER, whiteColor, false);
+            yPosition += List.ELEMENT_HEIGHT;
+            configureTitle(triggers, Raphael.rgb(41, 129, 255));
+
+            for (var i = 0; i < Elements.TRIGGERS.length; i++) {
+                var element: any = Elements.TRIGGERS[i];
+
+                if (this._viewer.root.type === Type.OBJECT && excludedTriggers.indexOf(i) !== -1) {
+                    continue;
+                }
+                else if (this._viewer.root.type === Type.SCENE && excludedTriggers.indexOf(i) === -1) {
+                    continue;
+                }
+
+                var trigger = this._createListElement(this.triggersList, yPosition, element.text, Type.TRIGGER, textColor, true, element);
+
+                trigger.rect.attr("fill", Raphael.rgb(133, 154, 185));
+                yPosition += List.ELEMENT_HEIGHT;
+            }
+
+            yPosition += List.ELEMENT_HEIGHT;
+            this.triggersElement.style.height = this.triggersList.canvas.style.height = yPosition + "px";
+            this._createCollapseAnimation(this.triggersList, this.triggersElement, triggers, yPosition);
+
+            // Create actions
+            yPosition = 10;
+            var actions = this._createListElement(this.actionsList, yPosition, "ACTIONS", Type.ACTION, textColor, false);
+            yPosition += List.ELEMENT_HEIGHT;
+            configureTitle(actions, Raphael.rgb(255, 220, 42));
+
+            for (var i = 0; i < Elements.ACTIONS.length; i++) {
+                var element: any = Elements.ACTIONS[i];
+                var action = this._createListElement(this.actionsList, yPosition, element.text, Type.ACTION, textColor, true, element);
+
+                action.rect.attr("fill", Raphael.rgb(182, 185, 132));
+                yPosition += List.ELEMENT_HEIGHT;
+            }
+
+            yPosition += List.ELEMENT_HEIGHT;
+            this.actionsElement.style.height = this.actionsList.canvas.style.height = yPosition + "px";
+            this._createCollapseAnimation(this.actionsList, this.actionsElement, actions, yPosition);
+
+            // Create flow controls
+            yPosition = 10;
+            var flowControls = this._createListElement(this.flowControlsList, yPosition, "FLOW CONTROLS", Type.FLOW_CONTROL, whiteColor, false);
+            yPosition += List.ELEMENT_HEIGHT;
+            configureTitle(flowControls, Raphael.rgb(255, 41, 53));
+
+            for (var i = 0; i < Elements.FLOW_CONTROLS.length - 1; i++) {
+                var element: any = Elements.FLOW_CONTROLS[i];
+                var flowControl = this._createListElement(this.flowControlsList, yPosition, element.text, Type.FLOW_CONTROL, textColor, true, element);
+
+                flowControl.rect.attr("fill", Raphael.rgb(185, 132, 140));
+                yPosition += List.ELEMENT_HEIGHT;
+            }
+
+            yPosition += List.ELEMENT_HEIGHT;
+            this.flowControlsElement.style.height = this.flowControlsList.canvas.style.height = yPosition + "px";
+            this._createCollapseAnimation(this.flowControlsList, this.flowControlsElement, flowControls, yPosition);
+        }
+
+        /**
+        * Clears the list of elements and removes the elements
+        */
+        public clearLists(): void {
+            for (var i = 0; i < this._listElements.length; i++) {
+                this._removeListElement(this._listElements[i]);
+            }
+            this._listElements.splice(0, this._listElements.length - 1);
+        }
+
+        /**
+        * Sets the color theme of the lists
+        * @param color: the theme color
+        */
+        public setColorTheme(color: string): void {
+            this.triggersList.canvas.style.backgroundColor = color;
+            this.actionsList.canvas.style.backgroundColor = color;
+            this.flowControlsList.canvas.style.backgroundColor = color;
+        }
+
+        /**
+        * Creates a list element
+        * @param paper: the Raphael.js paper
+        * @param yPosition: the y position of the element
+        * @param text: the element text
+        * @param type: the element type (trigger, action, flow control)
+        * @param textColor: the text color
+        * @param drag: if the element should be drag'n'dropped
+        */
+        private _createListElement(paper: Paper, yPosition: number, text: string, type: number,
+                                   textColor: RaphaelColor, drag: boolean, element?: Element): ListElement
+        {
+            var object = new ListElement();
+
+            object.rect = paper.rect(10, yPosition, 300, List.ELEMENT_HEIGHT);
+
+            object.text = paper.text(30, yPosition + object.rect.attr("height") / 2, text);
+            object.text.attr("fill", textColor);
+            object.text.attr("text-anchor", "start");
+            object.text.attr("font-size", "12");
+            object.text.attr("text-anchor", "start");
+            object.text.attr("font-family", "Sinkin Sans Light");
+
+            if (drag) {
+                this._createListElementAnimation(object);
+            }
+
+            object.type = type;
+            object.element = element;
+
+            this._listElements.push(object);
+            return object;
+        }
+
+        /**
+        * Removes a list element
+        * @param element: the element to remove
+        */
+        private _removeListElement(element: ListElement): void {
+            element.rect.remove();
+            element.text.remove();
+        }
+
+        /*
+        * Creates the collapse animation of a list
+        * @param paper: the list paper
+        * @param htmlElement: the list div container
+        * @param element: the list element to click on
+        * @param expandedHeight: the height when the list is expanded
+        */
+        private _createCollapseAnimation(paper: Paper, htmlElement: HTMLElement, element: ListElement, expandedHeight: number): void {
+            var onClick = (event: MouseEvent) => {
+                var height = htmlElement.style.height;
+                if (height === expandedHeight + "px") {
+                    htmlElement.style.height = paper.canvas.style.height = 35 + "px";
+                }
+                else {
+                    htmlElement.style.height = paper.canvas.style.height = expandedHeight + "px";
+                }
+            };
+
+            element.rect.click(onClick);
+        }
+
+        /*
+        * Creates the animation of a list element
+        * @param element: the list element to animate
+        */
+        private _createListElementAnimation(element: ListElement): void {
+            var onMove = (dx: number, dy: number, x: number, y: number) =>
+            { };
+
+            var onStart = (x: number, y: number, event: MouseEvent) => {
+                this._parentContainer.style.cursor = "copy";
+                element.rect.animate({
+                    x: -10,
+                    opacity: 0.25
+                }, 500, ">");
+                element.text.animate({
+                    x: 10,
+                    opacity: 0.25
+                }, 500, ">");
+            };
+
+            var onEnd = (event: MouseEvent) => {
+                this._parentContainer.style.cursor = "default";
+                element.rect.animate({
+                    x: 10,
+                    opacity: 1.0
+                }, 500, "<");
+                element.text.animate({
+                    x: 30,
+                    opacity: 1.0
+                }, 500, "<");
+
+                var dragResult = this._viewer.traverseGraph(null, this._viewer.mousex, this._viewer.mousey, false);
+
+                if (dragResult.hit) {
+                    if (element.type === Type.TRIGGER && dragResult.action !== this._viewer.root) {
+                        alert("Triggers can be dragged only on the root node (the mesh)");
+                        return;
+                    }
+
+                    if (element.type === Type.ACTION && dragResult.action === this._viewer.root) {
+                        alert("Please add a trigger before.");
+                        return;
+                    }
+
+                    //if (element.type === Type.FLOW_CONTROL && (dragResult.action === this._viewer.root || (dragResult.action.type === Type.FLOW_CONTROL && dragResult.action.parent.hub === null))) {
+                    if (element.type === Type.FLOW_CONTROL && dragResult.action === this._viewer.root) {
+                        return;
+                    }
+
+                    if (element.type === Type.FLOW_CONTROL && dragResult.action.combineArray !== null) {
+                        alert("A condition cannot be handled by a Combine Action.");
+                        return;
+                    }
+
+                    if ((element.type === Type.FLOW_CONTROL || element.type === Type.ACTION) && dragResult.action.type === Type.TRIGGER && dragResult.action.children.length > 0) {
+                        alert("Triggers can have only one child. Please add another trigger of same type.");
+                        return;
+                    }
+
+                    if (!(dragResult.action.combineArray !== null) && dragResult.action.children.length > 0 && dragResult.action.type !== Type.TRIGGER && dragResult.action !== this._viewer.root) {
+                        alert("An action can have only one child.");
+                        return;
+                    }
+
+                    this._viewer.addAction(dragResult.action, element.type, element.element);
+                    this._viewer.update();
+                }
+            };
+
+            element.rect.drag(onMove, onStart, onEnd);
+            element.text.drag(onMove, onStart, onEnd);
+        }
+
+    }
 }

+ 96 - 0
Exporters/3ds Max/ActionsBuilder/actionsbuilder.main.js

@@ -0,0 +1,96 @@
+/*
+Global functions called by the plugins (3ds Max, etc.)
+*/
+var list = null;
+var viewer = null;
+var actionsBuilderJsonInput = document.getElementById("ActionsBuilderJSON");
+this.createJSON = function () {
+    var structure = viewer.utils.createJSON(viewer.root);
+    var asText = JSON.stringify(structure);
+    actionsBuilderJsonInput.value = asText;
+    console.log(asText);
+};
+this.loadFromJSON = function () {
+    var json = actionsBuilderJsonInput.value;
+    if (json !== "") {
+        var structure = JSON.parse(json);
+        viewer.utils.loadFromJSON(structure, null);
+    }
+};
+this.updateObjectName = function () {
+    var element = document.getElementById("ActionsBuilderObjectName");
+    var name = element.value;
+    viewer.objectName = name;
+    if (viewer.root.type === ActionsBuilder.Type.OBJECT) {
+        name += " - Mesh";
+    }
+    else {
+        name += " - Scene";
+    }
+    viewer.root.node.text.attr("text", name);
+};
+this.resetList = function () {
+    list.clearLists();
+    list.createListsElements();
+};
+this.setMeshesNames = function () {
+    var args = [];
+    for (var _i = 0; _i < arguments.length; _i++) {
+        args[_i - 0] = arguments[_i];
+    }
+    for (var i = 0; i < args.length; i++) {
+        ActionsBuilder.SceneElements.MESHES.push(args[i]);
+    }
+};
+this.setLightsNames = function () {
+    var args = [];
+    for (var _i = 0; _i < arguments.length; _i++) {
+        args[_i - 0] = arguments[_i];
+    }
+    for (var i = 0; i < args.length; i++) {
+        ActionsBuilder.SceneElements.LIGHTS.push(args[i]);
+    }
+};
+this.setCamerasNames = function () {
+    var args = [];
+    for (var _i = 0; _i < arguments.length; _i++) {
+        args[_i - 0] = arguments[_i];
+    }
+    for (var i = 0; i < args.length; i++) {
+        ActionsBuilder.SceneElements.CAMERAS.push(args[i]);
+    }
+};
+this.setSoundsNames = function () {
+    var args = [];
+    for (var _i = 0; _i < arguments.length; _i++) {
+        args[_i - 0] = arguments[_i];
+    }
+    for (var i = 0; i < args.length; i++) {
+        var sound = args[i];
+        if (sound !== "" && ActionsBuilder.SceneElements.SOUNDS.indexOf(sound) === -1) {
+            ActionsBuilder.SceneElements.SOUNDS.push(args[i]);
+        }
+    }
+};
+this.hideButtons = function () {
+};
+this.setIsObject = function () {
+    viewer.root.type = ActionsBuilder.Type.OBJECT;
+};
+this.setIsScene = function () {
+    viewer.root.type = ActionsBuilder.Type.SCENE;
+};
+this.run = function () {
+    viewer = new ActionsBuilder.Viewer(ActionsBuilder.Type.OBJECT);
+    viewer.setColorTheme("-ms-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
+    viewer.setColorTheme("linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
+    viewer.setColorTheme("-webkit-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
+    viewer.setColorTheme("-o-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
+    viewer.onResize();
+    viewer.update();
+    list = new ActionsBuilder.List(viewer);
+    list.setColorTheme("rgb(64, 64, 64)");
+    list.createListsElements();
+    list.onResize();
+    viewer.onResize();
+};

+ 115 - 106
Exporters/3ds Max/ActionsBuilder/actionsbuilder.main.ts

@@ -1,109 +1,118 @@
-/*
-Global functions called by the plugins (3ds Max, etc.)
-*/
-
-// Elements
-
-var list: ActionsBuilder.List = null;
-var viewer: ActionsBuilder.Viewer = null;
-
-var actionsBuilderJsonInput: HTMLInputElement = <HTMLInputElement>document.getElementById("ActionsBuilderJSON");
-
-this.createJSON = () => {
-    var structure = viewer.utils.createJSON(viewer.root);
-    var asText = JSON.stringify(structure);
-    actionsBuilderJsonInput.value = asText;
-    console.log(asText);
-};
-
-this.loadFromJSON = () => {
-    var json = actionsBuilderJsonInput.value;
-    if (json !== "") {
-        var structure = JSON.parse(json);
-        viewer.utils.loadFromJSON(structure, null);
-    }
-};
-
-this.updateObjectName = () => {
-    var element = <HTMLInputElement>document.getElementById("ActionsBuilderObjectName");
-    var name = element.value;
-
-    viewer.objectName = name;
-
-    if (viewer.root.type === ActionsBuilder.Type.OBJECT) {
-        name += " - Mesh";
-    }
-    else {
-        name += " - Scene";
-    }
-
-    viewer.root.node.text.attr("text", name);
-};
-
-this.resetList = () => {
-    list.clearLists();
-    list.createListsElements();
-};
-
-this.setMeshesNames = (...args: string[]) => {
-    for (var i = 0; i < args.length; i++) {
-        ActionsBuilder.SceneElements.MESHES.push(args[i]);
-    }
-};
-
-this.setLightsNames = (...args: string[]) => {
-    for (var i = 0; i < args.length; i++) {
-        ActionsBuilder.SceneElements.LIGHTS.push(args[i]);
-    }
+/*
+Global functions called by the plugins (3ds Max, etc.)
+*/
+
+// Elements
+
+var list: ActionsBuilder.List = null;
+var viewer: ActionsBuilder.Viewer = null;
+
+var actionsBuilderJsonInput: HTMLInputElement = <HTMLInputElement>document.getElementById("ActionsBuilderJSON");
+
+this.getList = () => {
+    return list;
 };
 
-this.setCamerasNames = (...args: string[]) => {
-    for (var i = 0; i < args.length; i++) {
-        ActionsBuilder.SceneElements.CAMERAS.push(args[i]);
-    }
-};
-
-this.setSoundsNames = (...args: string[]) => {
-    for (var i = 0; i < args.length; i++) {
-        var sound = args[i];
-
-        if (sound !== "" && ActionsBuilder.SceneElements.SOUNDS.indexOf(sound) === -1) {
-            ActionsBuilder.SceneElements.SOUNDS.push(args[i]);
-        }
-    }
-};
-
-this.hideButtons = () => {
-    // Empty
-};
-
-this.setIsObject = () => {
-    viewer.root.type = ActionsBuilder.Type.OBJECT;
-};
-
-this.setIsScene = () => {
-    viewer.root.type = ActionsBuilder.Type.SCENE;
-};
-
-this.run = () => {
-    // Configure viewer
-    viewer = new ActionsBuilder.Viewer(ActionsBuilder.Type.OBJECT);
-
-    viewer.setColorTheme("-ms-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
-    viewer.setColorTheme("linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
-    viewer.setColorTheme("-webkit-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
-    viewer.setColorTheme("-o-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
-
-    viewer.onResize();
-    viewer.update();
-
-    // Configure list
-    list = new ActionsBuilder.List(viewer);
-    list.setColorTheme("rgb(64, 64, 64)");
-
-    list.createListsElements();
-    list.onResize();
-
-    // 3ds Max fix
-    viewer.onResize();
+this.getViewer = () => {
+    return viewer;
 };
+
+
+this.createJSON = () => {
+    var structure = viewer.utils.createJSON(viewer.root);
+    var asText = JSON.stringify(structure);
+    actionsBuilderJsonInput.value = asText;
+    console.log(asText);
+};
+
+this.loadFromJSON = () => {
+    var json = actionsBuilderJsonInput.value;
+    if (json !== "") {
+        var structure = JSON.parse(json);
+        viewer.utils.loadFromJSON(structure, null);
+    }
+};
+
+this.updateObjectName = () => {
+    var element = <HTMLInputElement>document.getElementById("ActionsBuilderObjectName");
+    var name = element.value;
+
+    viewer.objectName = name;
+
+    if (viewer.root.type === ActionsBuilder.Type.OBJECT) {
+        name += " - Mesh";
+    }
+    else {
+        name += " - Scene";
+    }
+
+    viewer.root.node.text.attr("text", name);
+};
+
+this.resetList = () => {
+    list.clearLists();
+    list.createListsElements();
+};
+
+this.setMeshesNames = (...args: string[]) => {
+    for (var i = 0; i < args.length; i++) {
+        ActionsBuilder.SceneElements.MESHES.push(args[i]);
+    }
+};
+
+this.setLightsNames = (...args: string[]) => {
+    for (var i = 0; i < args.length; i++) {
+        ActionsBuilder.SceneElements.LIGHTS.push(args[i]);
+    }
+};
+
+this.setCamerasNames = (...args: string[]) => {
+    for (var i = 0; i < args.length; i++) {
+        ActionsBuilder.SceneElements.CAMERAS.push(args[i]);
+    }
+};
+
+this.setSoundsNames = (...args: string[]) => {
+    for (var i = 0; i < args.length; i++) {
+        var sound = args[i];
+
+        if (sound !== "" && ActionsBuilder.SceneElements.SOUNDS.indexOf(sound) === -1) {
+            ActionsBuilder.SceneElements.SOUNDS.push(args[i]);
+        }
+    }
+};
+
+this.hideButtons = () => {
+    // Empty
+};
+
+this.setIsObject = () => {
+    viewer.root.type = ActionsBuilder.Type.OBJECT;
+};
+
+this.setIsScene = () => {
+    viewer.root.type = ActionsBuilder.Type.SCENE;
+};
+
+this.run = () => {
+    // Configure viewer
+    viewer = new ActionsBuilder.Viewer(ActionsBuilder.Type.OBJECT);
+
+    viewer.setColorTheme("-ms-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
+    viewer.setColorTheme("linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
+    viewer.setColorTheme("-webkit-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
+    viewer.setColorTheme("-o-linear-gradient(top, rgba(38, 38, 38,1) 0%, rgba(125, 126, 125, 1) 100%)");
+
+    viewer.onResize();
+    viewer.update();
+
+    // Configure list
+    list = new ActionsBuilder.List(viewer);
+    list.setColorTheme("rgb(64, 64, 64)");
+
+    list.createListsElements();
+    list.onResize();
+
+    // 3ds Max fix
+    viewer.onResize();
+};

+ 440 - 0
Exporters/3ds Max/ActionsBuilder/actionsbuilder.parameters.js

@@ -0,0 +1,440 @@
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    var Parameters = (function () {
+        function Parameters(viewer) {
+            var _this = this;
+            this._action = null;
+            this.parametersContainer = document.getElementById("ParametersElementID");
+            this.parametersHelpElement = document.getElementById("ParametersHelpElementID");
+            this._viewer = viewer;
+            window.addEventListener("resize", function (event) {
+                _this.onResize(event);
+            });
+        }
+        Parameters.prototype.clearParameters = function () {
+            if (this.parametersContainer.children === null) {
+                return;
+            }
+            while (this.parametersContainer.children.length > 0) {
+                this.parametersContainer.removeChild(this.parametersContainer.firstChild);
+            }
+        };
+        Parameters.prototype.createParameters = function (action) {
+            this._action = action;
+            this.clearParameters();
+            if (action === null) {
+                return;
+            }
+            this._createHelpSection(action);
+            this._createNodeSection(action);
+            var properties = action.properties;
+            var propertiesResults = action.propertiesResults;
+            var targetParameterSelect = null;
+            var targetParameterNameSelect = null;
+            var propertyPathSelect = null;
+            var propertyPathOptionalSelect = null;
+            var booleanSelect = null;
+            var propertyInput = null;
+            var propertyPathIndice = -1;
+            if (properties.length === 0) {
+                return;
+            }
+            for (var i = 0; i < properties.length; i++) {
+                var separator = document.createElement("hr");
+                separator.noShade = true;
+                separator.className = "ParametersElementSeparatorClass";
+                this.parametersContainer.appendChild(separator);
+                var parameterName = document.createElement("a");
+                parameterName.text = properties[i].text;
+                parameterName.className = "ParametersElementTitleClass";
+                this.parametersContainer.appendChild(parameterName);
+                if (properties[i].text === "parameter" || properties[i].text === "target" || properties[i].text === "parent") {
+                    targetParameterSelect = document.createElement("select");
+                    targetParameterSelect.className = "ParametersElementSelectClass";
+                    this.parametersContainer.appendChild(targetParameterSelect);
+                    targetParameterNameSelect = document.createElement("select");
+                    targetParameterNameSelect.className = "ParametersElementSelectClass";
+                    this.parametersContainer.appendChild(targetParameterNameSelect);
+                    (this._parameterTargetChanged(targetParameterSelect, targetParameterNameSelect, propertyPathSelect, propertyPathOptionalSelect, i))(null);
+                    targetParameterSelect.value = propertiesResults[i].targetType;
+                    targetParameterNameSelect.value = propertiesResults[i].value;
+                    targetParameterSelect.onchange = this._parameterTargetChanged(targetParameterSelect, targetParameterNameSelect, propertyPathSelect, propertyPathOptionalSelect, i);
+                    targetParameterNameSelect.onchange = this._parameterTargetNameChanged(targetParameterSelect, targetParameterNameSelect, i);
+                }
+                else if (properties[i].text === "propertyPath") {
+                    propertyPathIndice = i;
+                    propertyPathSelect = document.createElement("select");
+                    propertyPathSelect.className = "ParametersElementSelectClass";
+                    this.parametersContainer.appendChild(propertyPathSelect);
+                    propertyPathOptionalSelect = document.createElement("select");
+                    propertyPathOptionalSelect.className = "ParametersElementSelectClass";
+                    this.parametersContainer.appendChild(propertyPathOptionalSelect);
+                    (this._propertyPathSelectChanged(targetParameterSelect, propertyPathSelect, propertyPathOptionalSelect, null, null, i))(null);
+                    var property = this._action.propertiesResults[i].value.split(".");
+                    if (property.length > 0) {
+                        if (property.length === 1) {
+                            propertyPathSelect.value = property[0];
+                        }
+                        else {
+                            var completePropertyPath = "";
+                            for (var j = 0; j < property.length - 1; j++) {
+                                completePropertyPath += property[j];
+                                completePropertyPath += (j === property.length - 2) ? "" : ".";
+                            }
+                            propertyPathSelect.value = completePropertyPath;
+                            this._viewer.utils.setElementVisible(propertyPathOptionalSelect, true);
+                        }
+                        this._fillAdditionalPropertyPath(targetParameterSelect, propertyPathSelect, propertyPathOptionalSelect);
+                        propertyPathOptionalSelect.value = property[property.length - 1];
+                        if (propertyPathOptionalSelect.options.length === 0 || propertyPathOptionalSelect.options[0].text === "") {
+                            this._viewer.utils.setElementVisible(propertyPathOptionalSelect, false);
+                        }
+                    }
+                    targetParameterSelect.onchange = this._parameterTargetChanged(targetParameterSelect, targetParameterNameSelect, propertyPathSelect, propertyPathOptionalSelect, i - 1);
+                    propertyPathSelect.onchange = this._propertyPathSelectChanged(targetParameterSelect, propertyPathSelect, propertyPathOptionalSelect, null, null, i);
+                    propertyPathOptionalSelect.onchange = this._additionalPropertyPathSelectChanged(propertyPathSelect, propertyPathOptionalSelect, i);
+                }
+                else if (properties[i].text === "operator") {
+                    var conditionOperatorSelect = document.createElement("select");
+                    conditionOperatorSelect.className = "ParametersElementSelectClass";
+                    this.parametersContainer.appendChild(conditionOperatorSelect);
+                    (this._conditionOperatorSelectChanged(conditionOperatorSelect, i))(null);
+                    conditionOperatorSelect.value = propertiesResults[i].value;
+                    conditionOperatorSelect.onchange = this._conditionOperatorSelectChanged(conditionOperatorSelect, i);
+                }
+                else if (properties[i].text === "sound") {
+                    var soundSelect = document.createElement("select");
+                    soundSelect.className = "ParametersElementSelectClass";
+                    this.parametersContainer.appendChild(soundSelect);
+                    (this._soundSelectChanged(soundSelect, i))(null);
+                    soundSelect.value = propertiesResults[i].value;
+                    soundSelect.onchange = this._soundSelectChanged(soundSelect, i);
+                }
+                else {
+                    var isBoolean = propertiesResults[i].value === "true" || propertiesResults[i].value === "false";
+                    var object = this._getObjectFromType(targetParameterSelect.value);
+                    if (object !== null) {
+                        var property = this._action.propertiesResults[i - 1].value.split(".");
+                        for (var j = 0; j < property.length && object !== undefined; j++) {
+                            object = object[property[j]];
+                            if (j === property.length - 1) {
+                                isBoolean = isBoolean || typeof object === "boolean";
+                            }
+                        }
+                    }
+                    booleanSelect = document.createElement("select");
+                    booleanSelect.className = "ParametersElementSelectClass";
+                    this.parametersContainer.appendChild(booleanSelect);
+                    (this._booleanSelectChanged(booleanSelect, i))(null);
+                    booleanSelect.value = propertiesResults[i].value;
+                    booleanSelect.onchange = this._booleanSelectChanged(booleanSelect, i);
+                    propertyInput = document.createElement("input");
+                    propertyInput.value = propertiesResults[i].value;
+                    propertyInput.className = "ParametersElementInputClass";
+                    this.parametersContainer.appendChild(propertyInput);
+                    propertyInput.onkeyup = this._propertyInputChanged(propertyInput, i);
+                    if (propertyPathIndice !== -1 && properties[i].text === "value") {
+                        propertyPathSelect.onchange = this._propertyPathSelectChanged(targetParameterSelect, propertyPathSelect, propertyPathOptionalSelect, booleanSelect, propertyInput, propertyPathIndice);
+                    }
+                    if (isBoolean) {
+                        this._viewer.utils.setElementVisible(booleanSelect, true);
+                        this._viewer.utils.setElementVisible(propertyInput, false);
+                    }
+                    else {
+                        this._viewer.utils.setElementVisible(booleanSelect, false);
+                        this._viewer.utils.setElementVisible(propertyInput, true);
+                    }
+                }
+            }
+        };
+        Parameters.prototype.onResize = function (event) {
+            var tools = document.getElementById("ToolsButtonsID");
+            this.parametersContainer.style.height = window.innerHeight - tools.getBoundingClientRect().height - 25 - 200 + "px";
+            this.parametersHelpElement.style.height = 200 + "px";
+        };
+        Parameters.prototype._booleanSelectChanged = function (booleanSelect, indice) {
+            var _this = this;
+            return function (ev) {
+                if (booleanSelect.options.length === 0) {
+                    var values = ["true", "false"];
+                    for (var i = 0; i < values.length; i++) {
+                        var option = document.createElement("option");
+                        option.value = option.text = values[i];
+                        booleanSelect.options.add(option);
+                    }
+                }
+                else {
+                    _this._action.propertiesResults[indice].value = booleanSelect.value;
+                }
+            };
+        };
+        Parameters.prototype._soundSelectChanged = function (soundSelect, indice) {
+            var _this = this;
+            return function (ev) {
+                if (soundSelect.options.length === 0) {
+                    for (var i = 0; i < ActionsBuilder.SceneElements.SOUNDS.length; i++) {
+                        var option = document.createElement("option");
+                        option.value = option.text = ActionsBuilder.SceneElements.SOUNDS[i];
+                        soundSelect.options.add(option);
+                    }
+                    _this._sortList(soundSelect);
+                }
+                else {
+                    _this._action.propertiesResults[indice].value = soundSelect.value;
+                }
+            };
+        };
+        Parameters.prototype._conditionOperatorSelectChanged = function (conditionOperatorSelect, indice) {
+            var _this = this;
+            return function (ev) {
+                if (conditionOperatorSelect.options.length === 0) {
+                    for (var i = 0; i < ActionsBuilder.SceneElements.OPERATORS.length; i++) {
+                        var option = document.createElement("option");
+                        option.value = option.text = ActionsBuilder.SceneElements.OPERATORS[i];
+                        conditionOperatorSelect.options.add(option);
+                    }
+                }
+                else {
+                    _this._action.propertiesResults[indice].value = conditionOperatorSelect.value;
+                }
+            };
+        };
+        Parameters.prototype._propertyInputChanged = function (propertyInput, indice) {
+            var _this = this;
+            return function (ev) {
+                _this._action.propertiesResults[indice].value = propertyInput.value;
+            };
+        };
+        Parameters.prototype._propertyPathSelectChanged = function (targetParameterSelect, propertyPathSelect, additionalPropertyPathSelect, booleanSelect, propertyInput, indice) {
+            var _this = this;
+            return function (event) {
+                if (propertyPathSelect.options.length === 0) {
+                    var properties = _this._getPropertiesFromType(targetParameterSelect.value);
+                    if (properties !== null) {
+                        for (var i = 0; i < properties.length; i++) {
+                            var option = document.createElement("option");
+                            option.value = option.text = properties[i];
+                            propertyPathSelect.options.add(option);
+                        }
+                    }
+                }
+                else {
+                    _this._action.propertiesResults[indice].value = propertyPathSelect.value;
+                    if (booleanSelect !== null && propertyInput !== null) {
+                        var object = _this._getObjectFromType(targetParameterSelect.value);
+                        var isBoolean = false;
+                        if (object !== null) {
+                            var property = _this._action.propertiesResults[indice].value.split(".");
+                            for (var j = 0; j < property.length; j++) {
+                                object = object[property[j]];
+                                if (j === property.length - 1) {
+                                    isBoolean = isBoolean || typeof object === "boolean";
+                                }
+                            }
+                        }
+                        if (isBoolean) {
+                            _this._viewer.utils.setElementVisible(booleanSelect, true);
+                            _this._viewer.utils.setElementVisible(propertyInput, false);
+                        }
+                        else {
+                            _this._viewer.utils.setElementVisible(booleanSelect, false);
+                            _this._viewer.utils.setElementVisible(propertyInput, true);
+                        }
+                    }
+                }
+                _this._fillAdditionalPropertyPath(targetParameterSelect, propertyPathSelect, additionalPropertyPathSelect);
+                _this._sortList(propertyPathSelect);
+            };
+        };
+        Parameters.prototype._fillAdditionalPropertyPath = function (targetParameterSelect, propertyPathSelect, additionalPropertyPathSelect) {
+            additionalPropertyPathSelect.options.length = 0;
+            var object = this._getObjectFromType(targetParameterSelect.value);
+            if (object !== null) {
+                var propertyPath = propertyPathSelect.value.split(".");
+                for (var i = 0; i < propertyPath.length; i++) {
+                    object = object[propertyPath[i]];
+                }
+            }
+            if (object === null || object === undefined || (typeof (object)).toLowerCase() === "string") {
+                this._viewer.utils.setElementVisible(additionalPropertyPathSelect, false);
+                return;
+            }
+            var emptyOption = document.createElement("option");
+            emptyOption.value = emptyOption.text = "";
+            additionalPropertyPathSelect.add(emptyOption);
+            for (var thing in object) {
+                var type = ActionsBuilder.SceneElements.GetInstanceOf(object[thing]);
+                var index = ActionsBuilder.SceneElements.TYPES.indexOf(type);
+                if (index !== -1) {
+                    var option = document.createElement("option");
+                    option.value = option.text = thing;
+                    additionalPropertyPathSelect.options.add(option);
+                    emptyOption.text += thing + ", ";
+                }
+            }
+            if (additionalPropertyPathSelect.options.length === 0 || additionalPropertyPathSelect.options[0].text === "") {
+                this._viewer.utils.setElementVisible(additionalPropertyPathSelect, false);
+            }
+            else {
+                this._viewer.utils.setElementVisible(additionalPropertyPathSelect, true);
+            }
+        };
+        Parameters.prototype._additionalPropertyPathSelectChanged = function (propertyPathSelect, additionalPropertyPathSelect, indice) {
+            var _this = this;
+            return function (event) {
+                var property = propertyPathSelect.value;
+                var additionalProperty = additionalPropertyPathSelect.value;
+                if (additionalProperty !== "") {
+                    property += ".";
+                    property += additionalPropertyPathSelect.value;
+                }
+                _this._action.propertiesResults[indice].value = property;
+            };
+        };
+        Parameters.prototype._parameterTargetChanged = function (targetParameterSelect, targetParameterNameSelect, propertyPathSelect, additionalPropertyPathSelect, indice) {
+            var _this = this;
+            return function (event) {
+                if (targetParameterSelect.options.length === 0) {
+                    var options = [
+                        { text: "Mesh", targetType: "MeshProperties" },
+                        { text: "Light", targetType: "LightProperties" },
+                        { text: "Camera", targetType: "CameraProperties" },
+                        { text: "Scene", targetType: "SceneProperties" }
+                    ];
+                    targetParameterSelect.options.length = 0;
+                    for (var i = 0; i < options.length; i++) {
+                        var option = document.createElement("option");
+                        option.text = options[i].text;
+                        option.value = options[i].targetType;
+                        targetParameterSelect.options.add(option);
+                    }
+                    targetParameterSelect.value = _this._action.propertiesResults[indice].targetType;
+                }
+                else {
+                    _this._action.propertiesResults[indice].targetType = targetParameterSelect.value;
+                    var names = _this._getListFromType(targetParameterSelect.value);
+                    if (names !== null && names.length > 0) {
+                        _this._action.propertiesResults[indice].value = names[0];
+                    }
+                    else {
+                        _this._action.propertiesResults[indice].value = "";
+                    }
+                    if (propertyPathSelect !== null) {
+                        _this._action.propertiesResults[indice + 1].value = "";
+                    }
+                }
+                var targetParameterProperties = _this._getTargetFromType(targetParameterSelect.value);
+                targetParameterNameSelect.options.length = 0;
+                if (targetParameterProperties !== null) {
+                    for (var i = 0; i < targetParameterProperties.length; i++) {
+                        var option = document.createElement("option");
+                        option.text = option.value = targetParameterProperties[i];
+                        targetParameterNameSelect.options.add(option);
+                    }
+                }
+                targetParameterNameSelect.value = _this._action.propertiesResults[indice].value;
+                if (propertyPathSelect !== null) {
+                    propertyPathSelect.options.length = 0;
+                    additionalPropertyPathSelect.options.length = 0;
+                    _this._propertyPathSelectChanged(targetParameterSelect, propertyPathSelect, additionalPropertyPathSelect, null, null, indice + 1)(null);
+                }
+                _this._sortList(targetParameterNameSelect);
+                _this._sortList(targetParameterSelect);
+            };
+        };
+        Parameters.prototype._parameterTargetNameChanged = function (targetParameterSelect, targetParameterNameSelect, indice) {
+            var _this = this;
+            return function (event) {
+                _this._action.propertiesResults[indice].value = targetParameterNameSelect.value;
+            };
+        };
+        Parameters.prototype._getTargetFromType = function (type) {
+            if (type === "MeshProperties" || type === "Mesh") {
+                return ActionsBuilder.SceneElements.MESHES;
+            }
+            if (type === "LightProperties" || type === "Light") {
+                return ActionsBuilder.SceneElements.LIGHTS;
+            }
+            if (type === "CameraProperties" || type === "Camera") {
+                return ActionsBuilder.SceneElements.CAMERAS;
+            }
+            return null;
+        };
+        Parameters.prototype._getPropertiesFromType = function (type) {
+            if (type === "MeshProperties" || type === "Mesh") {
+                return ActionsBuilder.SceneElements.MESH_PROPERTIES;
+            }
+            if (type === "LightProperties" || type === "Light") {
+                return ActionsBuilder.SceneElements.LIGHT_PROPERTIES;
+            }
+            if (type === "CameraProperties" || type === "Camera") {
+                return ActionsBuilder.SceneElements.CAMERA_PROPERTIES;
+            }
+            if (type === "SceneProperties" || type === "Scene") {
+                return ActionsBuilder.SceneElements.SCENE_PROPERTIES;
+            }
+            return null;
+        };
+        Parameters.prototype._getListFromType = function (type) {
+            if (type === "MeshProperties" || type === "Mesh") {
+                return ActionsBuilder.SceneElements.MESHES;
+            }
+            if (type === "LightProperties" || type === "Light") {
+                return ActionsBuilder.SceneElements.LIGHTS;
+            }
+            if (type === "CameraProperties" || type === "Camera") {
+                return ActionsBuilder.SceneElements.CAMERAS;
+            }
+            return null;
+        };
+        Parameters.prototype._getObjectFromType = function (type) {
+            if (type === "MeshProperties" || type === "Mesh") {
+                this._currentObject = ActionsBuilder.SceneElements.MESH;
+                return ActionsBuilder.SceneElements.MESH;
+            }
+            if (type === "LightProperties" || type === "Light") {
+                this._currentObject = ActionsBuilder.SceneElements.LIGHT;
+                return ActionsBuilder.SceneElements.LIGHT;
+            }
+            if (type === "CameraProperties" || type === "Camera") {
+                this._currentObject = ActionsBuilder.SceneElements.CAMERA;
+                return ActionsBuilder.SceneElements.CAMERA;
+            }
+            if (type === "SceneProperties" || type === "Scene") {
+                this._currentObject = ActionsBuilder.SceneElements.SCENE;
+                return ActionsBuilder.SceneElements.SCENE;
+            }
+            return null;
+        };
+        Parameters.prototype._createNodeSection = function (action) {
+            var element = document.createElement("div");
+            element.style.background = this._viewer.getSelectedNodeColor(action.type, action.node.detached);
+            element.className = "ParametersElementNodeClass";
+            var text = document.createElement("a");
+            text.text = action.name;
+            text.className = "ParametersElementNodeTextClass";
+            element.appendChild(text);
+            this.parametersContainer.appendChild(element);
+        };
+        Parameters.prototype._createHelpSection = function (action) {
+            var element = ActionsBuilder.Elements.GetElementFromName(action.name);
+            if (element !== null) {
+                this.parametersHelpElement.textContent = element.description;
+            }
+        };
+        Parameters.prototype._sortList = function (element) {
+            var options = [];
+            for (var i = element.options.length - 1; i >= 0; i--) {
+                options.push(element.removeChild(element.options[i]));
+            }
+            options.sort(function (a, b) {
+                return a.innerHTML.localeCompare(b.innerHTML);
+            });
+            for (var i = 0; i < options.length; i++) {
+                element.options.add(options[i]);
+            }
+        };
+        return Parameters;
+    })();
+    ActionsBuilder.Parameters = Parameters;
+})(ActionsBuilder || (ActionsBuilder = {}));

文件差異過大導致無法顯示
+ 649 - 637
Exporters/3ds Max/ActionsBuilder/actionsbuilder.parameters.ts


+ 80 - 0
Exporters/3ds Max/ActionsBuilder/actionsbuilder.toolbar.js

@@ -0,0 +1,80 @@
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    var Toolbar = (function () {
+        function Toolbar(viewer) {
+            var _this = this;
+            this.toolbarElement = document.getElementById("ToolbarElementID");
+            this._viewer = viewer;
+            window.addEventListener("resize", function (event) {
+                _this.onResize();
+            });
+            document.getElementById("ViewerDeZoomID").addEventListener("click", function (event) {
+                if (_this._viewer.zoom > 0.1) {
+                    _this._viewer.zoom -= 0.1;
+                }
+                _this._viewer.update();
+            });
+            document.getElementById("ViewerZoomID").addEventListener("click", function (event) {
+                if (_this._viewer.zoom < 1.0) {
+                    _this._viewer.zoom += 0.1;
+                }
+                _this._viewer.update();
+            });
+            document.getElementById("ViewerReconnectAll").addEventListener("click", function (event) {
+                for (var i = 0; i < _this._viewer.root.children.length; i++) {
+                    _this._viewer.selectedNode = _this._viewer.root.children[i];
+                    _this._viewer.utils.onDetachAction(false, true);
+                }
+                _this._viewer.update();
+                _this._viewer.selectedNode = null;
+            });
+            document.getElementById("ViewerDisconnectAll").addEventListener("click", function (event) {
+                for (var i = 0; i < _this._viewer.root.children.length; i++) {
+                    _this._viewer.selectedNode = _this._viewer.root.children[i];
+                    _this._viewer.utils.onDetachAction(true, false);
+                }
+                _this._viewer.update();
+                _this._viewer.selectedNode = null;
+            });
+            document.getElementById("ViewerReduceAll").addEventListener("click", function (event) {
+                for (var i = 0; i < _this._viewer.root.children.length; i++) {
+                    _this._viewer.selectedNode = _this._viewer.root.children[i];
+                    _this._viewer.utils.onReduceAll(false);
+                }
+                _this._viewer.update();
+                _this._viewer.selectedNode = null;
+            });
+            document.getElementById("ViewerExpandAll").addEventListener("click", function (event) {
+                for (var i = 0; i < _this._viewer.root.children.length; i++) {
+                    _this._viewer.selectedNode = _this._viewer.root.children[i];
+                    _this._viewer.utils.onReduceAll(true);
+                }
+                _this._viewer.update();
+                _this._viewer.selectedNode = null;
+            });
+            this.saveActionGraphElement = document.getElementById("ToolsButtonIDSaveActionGraph");
+            this.drawSaveActionGraphButton(false);
+            document.getElementById("ResetActionGraphID").addEventListener("click", function (event) {
+                if (confirm("Are you sure?")) {
+                    for (var i = 0; i < _this._viewer.root.children.length; i++) {
+                        _this._viewer.selectedNode = _this._viewer.root.children[i];
+                        _this._viewer.utils.onRemoveBranch();
+                    }
+                    _this._viewer.update();
+                    _this._viewer.selectedNode = null;
+                }
+            });
+            document.getElementById("TestActionGraphID").addEventListener("click", function (event) {
+                _this._viewer.utils.onTestGraph();
+            });
+        }
+        Toolbar.prototype.onResize = function () {
+            this.toolbarElement.style.top = this._viewer.viewerElement.clientHeight + 20 + "px";
+        };
+        Toolbar.prototype.drawSaveActionGraphButton = function (draw) {
+            this.saveActionGraphElement.style.display = draw ? "block" : "none";
+        };
+        return Toolbar;
+    })();
+    ActionsBuilder.Toolbar = Toolbar;
+})(ActionsBuilder || (ActionsBuilder = {}));

+ 93 - 93
Exporters/3ds Max/ActionsBuilder/actionsbuilder.toolbar.ts

@@ -1,94 +1,94 @@
-module ActionsBuilder {
-    export class Toolbar {
-        public toolbarElement: HTMLElement;
-        public saveActionGraphElement: HTMLElement;
-
-        private _viewer: Viewer;
-
-        constructor(viewer: Viewer) {
-            // Get HTML elements
-            this.toolbarElement = document.getElementById("ToolbarElementID");
-
-            // Configure this
-            this._viewer = viewer;
-
-            // Manage events
-            window.addEventListener("resize", (event: Event) => {
-                this.onResize();
-            });
-
-            // Bottom toolbar
-            document.getElementById("ViewerDeZoomID").addEventListener("click", (event: MouseEvent) => {
-                if (this._viewer.zoom > 0.1) {
-                    this._viewer.zoom -= 0.1;
-                }
-                this._viewer.update();
-            });
-            document.getElementById("ViewerZoomID").addEventListener("click", (event: MouseEvent) => {
-                if (this._viewer.zoom < 1.0) {
-                    this._viewer.zoom += 0.1;
-                }
-                this._viewer.update();
-            });
-            document.getElementById("ViewerReconnectAll").addEventListener("click", (event: MouseEvent) => {
-                for (var i = 0; i < this._viewer.root.children.length; i++) {
-                    this._viewer.selectedNode = this._viewer.root.children[i];
-                    this._viewer.utils.onDetachAction(false, true);
-                }
-                this._viewer.update();
-                this._viewer.selectedNode = null;
-            });
-            document.getElementById("ViewerDisconnectAll").addEventListener("click", (event: MouseEvent) => {
-                for (var i = 0; i < this._viewer.root.children.length; i++) {
-                    this._viewer.selectedNode = this._viewer.root.children[i];
-                    this._viewer.utils.onDetachAction(true, false);
-                }
-                this._viewer.update();
-                this._viewer.selectedNode = null;
-            });
-            document.getElementById("ViewerReduceAll").addEventListener("click", (event: MouseEvent) => {
-                for (var i = 0; i < this._viewer.root.children.length; i++) {
-                    this._viewer.selectedNode = this._viewer.root.children[i];
-                    this._viewer.utils.onReduceAll(false);
-                }
-                this._viewer.update();
-                this._viewer.selectedNode = null;
-            });
-            document.getElementById("ViewerExpandAll").addEventListener("click", (event: MouseEvent) => {
-                for (var i = 0; i < this._viewer.root.children.length; i++) {
-                    this._viewer.selectedNode = this._viewer.root.children[i];
-                    this._viewer.utils.onReduceAll(true);
-                }
-                this._viewer.update();
-                this._viewer.selectedNode = null;
-            });
-
-            // Top toolbar
-            this.saveActionGraphElement = document.getElementById("ToolsButtonIDSaveActionGraph");
-            this.drawSaveActionGraphButton(false);
-
-            document.getElementById("ResetActionGraphID").addEventListener("click", (event: MouseEvent) => {
-                if (confirm("Are you sure?")) {
-                    for (var i = 0; i < this._viewer.root.children.length; i++) {
-                        this._viewer.selectedNode = this._viewer.root.children[i];
-                        this._viewer.utils.onRemoveBranch();
-                    }
-                    this._viewer.update();
-                    this._viewer.selectedNode = null;
-                }
-            });
-            document.getElementById("TestActionGraphID").addEventListener("click", (event: MouseEvent) => {
-                this._viewer.utils.onTestGraph();
-            });
-        }
-
-        public onResize(): void {
-            this.toolbarElement.style.top = this._viewer.viewerElement.clientHeight + 20 + "px";
-        }
-
-        public drawSaveActionGraphButton(draw: boolean) {
-            this.saveActionGraphElement.style.display = draw ? "block" : "none";
-        }
-    }
-}
+module ActionsBuilder {
+    export class Toolbar {
+        public toolbarElement: HTMLElement;
+        public saveActionGraphElement: HTMLElement;
+
+        private _viewer: Viewer;
+
+        constructor(viewer: Viewer) {
+            // Get HTML elements
+            this.toolbarElement = document.getElementById("ToolbarElementID");
+
+            // Configure this
+            this._viewer = viewer;
+
+            // Manage events
+            window.addEventListener("resize", (event: Event) => {
+                this.onResize();
+            });
+
+            // Bottom toolbar
+            document.getElementById("ViewerDeZoomID").addEventListener("click", (event: MouseEvent) => {
+                if (this._viewer.zoom > 0.1) {
+                    this._viewer.zoom -= 0.1;
+                }
+                this._viewer.update();
+            });
+            document.getElementById("ViewerZoomID").addEventListener("click", (event: MouseEvent) => {
+                if (this._viewer.zoom < 1.0) {
+                    this._viewer.zoom += 0.1;
+                }
+                this._viewer.update();
+            });
+            document.getElementById("ViewerReconnectAll").addEventListener("click", (event: MouseEvent) => {
+                for (var i = 0; i < this._viewer.root.children.length; i++) {
+                    this._viewer.selectedNode = this._viewer.root.children[i];
+                    this._viewer.utils.onDetachAction(false, true);
+                }
+                this._viewer.update();
+                this._viewer.selectedNode = null;
+            });
+            document.getElementById("ViewerDisconnectAll").addEventListener("click", (event: MouseEvent) => {
+                for (var i = 0; i < this._viewer.root.children.length; i++) {
+                    this._viewer.selectedNode = this._viewer.root.children[i];
+                    this._viewer.utils.onDetachAction(true, false);
+                }
+                this._viewer.update();
+                this._viewer.selectedNode = null;
+            });
+            document.getElementById("ViewerReduceAll").addEventListener("click", (event: MouseEvent) => {
+                for (var i = 0; i < this._viewer.root.children.length; i++) {
+                    this._viewer.selectedNode = this._viewer.root.children[i];
+                    this._viewer.utils.onReduceAll(false);
+                }
+                this._viewer.update();
+                this._viewer.selectedNode = null;
+            });
+            document.getElementById("ViewerExpandAll").addEventListener("click", (event: MouseEvent) => {
+                for (var i = 0; i < this._viewer.root.children.length; i++) {
+                    this._viewer.selectedNode = this._viewer.root.children[i];
+                    this._viewer.utils.onReduceAll(true);
+                }
+                this._viewer.update();
+                this._viewer.selectedNode = null;
+            });
+
+            // Top toolbar
+            this.saveActionGraphElement = document.getElementById("ToolsButtonIDSaveActionGraph");
+            this.drawSaveActionGraphButton(false);
+
+            document.getElementById("ResetActionGraphID").addEventListener("click", (event: MouseEvent) => {
+                if (confirm("Are you sure?")) {
+                    for (var i = 0; i < this._viewer.root.children.length; i++) {
+                        this._viewer.selectedNode = this._viewer.root.children[i];
+                        this._viewer.utils.onRemoveBranch();
+                    }
+                    this._viewer.update();
+                    this._viewer.selectedNode = null;
+                }
+            });
+            document.getElementById("TestActionGraphID").addEventListener("click", (event: MouseEvent) => {
+                this._viewer.utils.onTestGraph();
+            });
+        }
+
+        public onResize(): void {
+            this.toolbarElement.style.top = this._viewer.viewerElement.clientHeight + 20 + "px";
+        }
+
+        public drawSaveActionGraphButton(draw: boolean) {
+            this.saveActionGraphElement.style.display = draw ? "block" : "none";
+        }
+    }
+}
  

+ 326 - 326
Exporters/3ds Max/ActionsBuilder/actionsbuilder.ts

@@ -1,326 +1,326 @@
-module ActionsBuilder {
-
-    /**
-    * Defines static types
-    */
-    export class Type {
-        private static _TRIGGER = 0;
-        private static _ACTION = 1;
-        private static _FLOW_CONTROL = 2;
-        private static _OBJECT = 3;
-        private static _SCENE = 4;
-
-        public static get TRIGGER(): number {
-            return Type._TRIGGER;
-        }
-
-        public static get ACTION(): number {
-            return Type._ACTION;
-        }
-
-        public static get FLOW_CONTROL(): number {
-            return Type._FLOW_CONTROL;
-        }
-
-        public static get OBJECT(): number {
-            return Type._OBJECT;
-        }
-
-        public static get SCENE(): number {
-            return Type._SCENE;
-        }
-    }
-
-    /*
-    * Defines the BABYLON.JS elements
-    */
-    export class SceneElements {
-        /*
-        * BabylonJS objects
-        */
-        private static _ENGINE: BABYLON.Engine = new BABYLON.Engine(<HTMLCanvasElement>document.getElementById("RenderCanvasID"));
-        private static _SCENE: BABYLON.Scene = new BABYLON.Scene(SceneElements.ENGINE);
-        private static _MESH: BABYLON.Mesh = new BABYLON.Mesh("mesh", SceneElements._SCENE);
-        private static _LIGHT: BABYLON.Light = new BABYLON.Light("light", SceneElements._SCENE);
-        private static _CAMERA: BABYLON.Camera = new BABYLON.Camera("camera", BABYLON.Vector3.Zero(), SceneElements._SCENE);
-
-        public static get ENGINE(): BABYLON.Engine {
-            return SceneElements._ENGINE;
-        }
-
-        public static get SCENE(): BABYLON.Scene {
-            return SceneElements._SCENE;
-        }
-
-        public static get MESH(): BABYLON.Mesh {
-            return SceneElements._MESH;
-        }
-
-        public static get LIGHT(): BABYLON.Light {
-            return SceneElements._LIGHT;
-        }
-
-        public static get CAMERA(): BABYLON.Camera {
-            return SceneElements._CAMERA;
-        }
-
-        /*
-        * Objects names
-        */
-        private static _MESHES = new Array<string>();
-        private static _LIGHTS = new Array<string>();
-        private static _CAMERAS = new Array<string>();
-        private static _SOUNDS = new Array<string>();
-
-        public static get MESHES(): Array<string> {
-            return SceneElements._MESHES;
-        }
-
-        public static get LIGHTS(): Array<string> {
-            return SceneElements._LIGHTS;
-        }
-
-        public static get CAMERAS(): Array<string> {
-            return SceneElements._CAMERAS;
-        }
-
-        public static get SOUNDS(): Array<string> {
-            return SceneElements._SOUNDS;
-        }
-
-        /*
-        * Properties
-        */
-        private static _MESH_PROPERTIES = new Array<string>();
-        private static _LIGHT_PROPERTIES = new Array<string>();
-        private static _CAMERA_PROPERTIES = new Array<string>();
-        private static _SCENE_PROPERTIES = new Array<string>();
-
-        public static get MESH_PROPERTIES(): Array<string> {
-            return SceneElements._MESH_PROPERTIES;
-        }
-
-        public static get LIGHT_PROPERTIES(): Array<string> {
-            return SceneElements._LIGHT_PROPERTIES;
-        }
-
-        public static get CAMERA_PROPERTIES(): Array<string> {
-            return SceneElements._CAMERA_PROPERTIES;
-        }
-
-        public static get SCENE_PROPERTIES(): Array<string> {
-            return SceneElements._SCENE_PROPERTIES;
-        }
-
-        /*
-        * Types
-        */
-        private static _TYPES = new Array<string>();
-
-        public static get TYPES(): Array<string> {
-            return SceneElements._TYPES;
-        }
-
-        /*
-        * Operators
-        */
-        private static _OPERATORS = new Array<string>();
-
-        public static get OPERATORS(): Array<string> {
-            return SceneElements._OPERATORS;
-        }
-
-        /*
-        * Methods
-        */
-        public static GetInstanceOf(object: Object): string {
-            if (object === null || object === undefined) {
-                return "";
-            }
-            return object.constructor.toString().match(/function (\w*)/)[1];
-        }
-
-        public static TestInstanceOf (object: Object, propertyName: string): boolean {
-            if (object === null || object.constructor === null) {
-                return false;
-            }
-
-            if (propertyName.length > 0 && propertyName[0] === "_")
-                return false;
-
-            var name = SceneElements.GetInstanceOf(object);
-
-            for (var i = 0; i < SceneElements.TYPES.length; i++) {
-                if (name === SceneElements.TYPES[i]) {
-                    return true;
-                }
-            }
-
-            return false;
-        }
-    }
-
-    // Functions
-    var specialTypes = [
-        "StandardMaterial"
-    ];
-    SceneElements.MESH.material = new BABYLON.StandardMaterial("material", SceneElements.SCENE);
-
-    var addSpecialType = (object: any, properties: Array<string>, thing: string) => {
-        for (var specialThing in object[thing]) {
-            if (object[thing].hasOwnProperty(specialThing) && SceneElements.TestInstanceOf(object[thing][specialThing], specialThing)) {
-                properties.push(thing + "." + specialThing);
-            }
-        }
-    };
-
-    // Configure types
-    SceneElements.TYPES.push("Color3");
-    SceneElements.TYPES.push("Boolean");
-    SceneElements.TYPES.push("Number");
-    SceneElements.TYPES.push("Vector2");
-    SceneElements.TYPES.push("Vector3");
-    SceneElements.TYPES.push("String");
-
-    // Configure operators
-    SceneElements.OPERATORS.push("IsEqual");
-    SceneElements.OPERATORS.push("IsDifferent");
-    SceneElements.OPERATORS.push("IsGreater");
-    SceneElements.OPERATORS.push("IsLesser");
-
-    // Configure properties
-    for (var thing in SceneElements.MESH) {
-        var instance = SceneElements.GetInstanceOf(SceneElements.MESH[thing]);
-
-        if (SceneElements.MESH.hasOwnProperty(thing)) {
-            if (specialTypes.indexOf(instance) !== -1) {
-                addSpecialType(SceneElements.MESH, SceneElements.MESH_PROPERTIES, thing);
-            }
-            else if (SceneElements.TestInstanceOf(SceneElements.MESH[thing], thing)) {
-                SceneElements.MESH_PROPERTIES.push(thing);
-            }
-        }
-    }
-
-    for (var thing in SceneElements.LIGHT) {
-        if (SceneElements.LIGHT.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.LIGHT[thing], thing)) {
-            SceneElements.LIGHT_PROPERTIES.push(thing);
-        }
-    }
-
-    for (var thing in SceneElements.CAMERA) {
-        if (SceneElements.CAMERA.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.CAMERA[thing], thing)) {
-            SceneElements.CAMERA_PROPERTIES.push(thing);
-        }
-    }
-
-    for (var thing in SceneElements.SCENE) {
-        if (SceneElements.SCENE.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.SCENE[thing], thing)) {
-            SceneElements.SCENE_PROPERTIES.push(thing);
-        }
-    }
-
-    /**
-    * Defines an element property
-    */
-    export interface ElementProperty {
-        targetType?: string;
-        text: string;
-        value: string;
-    }
-
-    /**
-    * Defines an element property result
-    */
-    export interface ElementPropertyResult {
-        targetType?: string;
-        value: string;
-    }
-
-    /**
-    * Generic element, has a name, a text to draw, a description
-    * and a list of properties (ElementProperty)
-    */
-    export interface Element {
-        name: string;
-        text: string;
-        properties: Array<ElementProperty>;
-        description: string;
-    }
-
-    /**
-    * Actions Builder elements (triggers, actions & flow controls) that are
-    * arrays of Element
-    */
-    export class Elements {
-        private static _TRIGGERS = new Array<Element>();
-        private static _ACTIONS = new Array<Element>();
-        private static _FLOW_CONTROLS = new Array<Element>();
-
-        public static get TRIGGERS(): Array<Element> {
-            return Elements._TRIGGERS;
-        }
-
-        public static get ACTIONS(): Array<Element> {
-            return Elements._ACTIONS;
-        }
-
-        public static get FLOW_CONTROLS(): Array<Element> {
-            return Elements._FLOW_CONTROLS;
-        }
-
-        public static GetElementFromName(name: string): Element {
-            for (var i = 0; i < Elements.TRIGGERS.length; i++) {
-                if (Elements.TRIGGERS[i].name === name) {
-                    return Elements._TRIGGERS[i];
-                }
-            }
-
-            for (var i = 0; i < Elements.ACTIONS.length; i++) {
-                if (Elements.ACTIONS[i].name === name) {
-                    return Elements._ACTIONS[i];
-                }
-            }
-
-            for (var i = 0; i < Elements.FLOW_CONTROLS.length; i++) {
-                if (Elements.FLOW_CONTROLS[i].name === name) {
-                    return Elements._FLOW_CONTROLS[i];
-                }
-            }
-
-            return null;
-        }
-    }
-
-    // Configure triggers
-    Elements.TRIGGERS.push({ name: "OnPickTrigger", text: "pick", properties: [], description: "When the user picks the edited mesh" });
-    Elements.TRIGGERS.push({ name: "OnLeftPickTrigger", text: "left pick", properties: [], description: "When the user picks the edited mesh using the left click" });
-    Elements.TRIGGERS.push({ name: "OnRightPickTrigger", text: "right pick", properties: [], description: "When the user picks the edited mesh using the right click" });
-    Elements.TRIGGERS.push({ name: "OnCenterPickTrigger", text: "center pick", properties: [], description: "When the user picks the edited mesh using the click of the mouse wheel" });
-    Elements.TRIGGERS.push({ name: "OnPointerOverTrigger", text: "pointer over", properties: [], description: "When the user's mouse is over the edited mesh" });
-    Elements.TRIGGERS.push({ name: "OnPointerOutTrigger", text: "pointer out", properties: [], description: "When the user's mouse is out of the edited mesh" });
-    Elements.TRIGGERS.push({ name: "OnEveryFrameTrigger", text: "every frame", properties: [], description: "This trigger is called each frame (only on scene)" });
-    Elements.TRIGGERS.push({ name: "OnIntersectionEnterTrigger", text: "intersection enter", properties: [{ targetType: "MeshProperties", text: "parameter", value: "Object name?" }], description: "When the edited mesh intersects the another mesh predefined in the options" });
-    Elements.TRIGGERS.push({ name: "OnIntersectionExitTrigger", text: "intersection exit", properties: [{ targetType: "MeshProperties", text: "parameter", value: "Object name?" }], description: "When the edited mesh exits intersection with the another mesh predefined in the options" });
-    Elements.TRIGGERS.push({ name: "OnKeyDownTrigger", text: "key down", properties: [{ targetType: null, text: "parameter:", value: "a" }], description: "When the user pressed a key (enter the key character, example: \"r\")" });
-    Elements.TRIGGERS.push({ name: "OnKeyUpTrigger", text: "key up", properties: [{ targetType: null, text: "parameter:", value: "a" }], description: "When the user unpressed a key (enter the key character, example: \"p\")" });
-
-    // Configure actions
-    Elements.ACTIONS.push({ name: "SwitchBooleanAction", text: "switch boolean", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }], description: "Switches the boolean value of a given parameter of the target object: true to false, or false to true" });
-    Elements.ACTIONS.push({ name: "SetStateAction", text: "set state", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "value", value: "" }], description: "Sets a new state value for the target object (example: \"off\" or \"on\")" });
-    Elements.ACTIONS.push({ name: "SetValueAction", text: "set value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }], description: "Sets a new value to the specified parameter of the target object (example: position.x to 0.0)" });
-    Elements.ACTIONS.push({ name: "SetParentAction", text: "set parent", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "parent", value: "" }], description: "Sets the new parent of the target object (example: a mesh or a light)" });
-    Elements.ACTIONS.push({ name: "IncrementValueAction", text: "increment value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }], description: "Increments the value of the given parameter of the target object. The value can be negative. (example: increment position.x of 5.0)" });
-    Elements.ACTIONS.push({ name: "PlayAnimationAction", text: "play animation", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "from", value: "0" }, { text: "to", value: "150" }, { text: "loop", value: "false" }], description: "Plays an animation of the target object. Specify the start frame, the end frame and if the animation should loop." });
-    Elements.ACTIONS.push({ name: "StopAnimationAction", text: "stop animation", properties: [{ targetType: "MeshProperties", text: "target", value: "" }], description: "Stops the animations of the target object." });
-    Elements.ACTIONS.push({ name: "DoNothingAction", text: "do nothing", properties: [], description: "Does nothing, can be used to balance/equilibrate the actions graph." });
-    Elements.ACTIONS.push({ name: "InterpolateValueAction", text: "interpolate value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "0" }, { text: "duration", value: "1000" }, { text: "stopOtherAnimations", value: "false" }], description: "Creates an animation (key frames) that animates the target object by interpolating the given parameter of the target value." });
-    Elements.ACTIONS.push({ name: "PlaySoundAction", text: "play sound", properties: [{ text: "sound", value: "" }], description: "Plays the specified sound." });
-    Elements.ACTIONS.push({ name: "StopSoundAction", text: "stop sound", properties: [{ text: "sound", value: "" }], description: "Stops the specified sound." });
-    Elements.ACTIONS.push({ name: "CombineAction", text: "combine", properties: [], description: "Special action that combines multiple actions. The combined actions are executed at the same time. Drag'n'drop the new actions inside to combine actions." });
-
-    // Configure flow control
-    Elements.FLOW_CONTROLS.push({ name: "ValueCondition", text: "value condition", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }, { text: "operator", value: SceneElements.OPERATORS[0] }], description: "A condition checking if a given value is equal, different, lesser or greater than the given parameter of the target object" });
-    Elements.FLOW_CONTROLS.push({ name: "StateCondition", text: "state condition", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "value", value: "" }], description: "A condition checking if the target object's state is equal to the given state. See \"set state\" action to set a state to an object." });
-    Elements.FLOW_CONTROLS.push({ name: "Hub", text: "hub", properties: [], description: "The hub is internally used by the Combine Action. It allows to add children to the Combine Action" });
-}
+module ActionsBuilder {
+
+    /**
+    * Defines static types
+    */
+    export class Type {
+        private static _TRIGGER = 0;
+        private static _ACTION = 1;
+        private static _FLOW_CONTROL = 2;
+        private static _OBJECT = 3;
+        private static _SCENE = 4;
+
+        public static get TRIGGER(): number {
+            return Type._TRIGGER;
+        }
+
+        public static get ACTION(): number {
+            return Type._ACTION;
+        }
+
+        public static get FLOW_CONTROL(): number {
+            return Type._FLOW_CONTROL;
+        }
+
+        public static get OBJECT(): number {
+            return Type._OBJECT;
+        }
+
+        public static get SCENE(): number {
+            return Type._SCENE;
+        }
+    }
+
+    /*
+    * Defines the BABYLON.JS elements
+    */
+    export class SceneElements {
+        /*
+        * BabylonJS objects
+        */
+        private static _ENGINE: BABYLON.Engine = new BABYLON.Engine(<HTMLCanvasElement>document.getElementById("RenderCanvasID"));
+        private static _SCENE: BABYLON.Scene = new BABYLON.Scene(SceneElements.ENGINE);
+        private static _MESH: BABYLON.Mesh = new BABYLON.Mesh("mesh", SceneElements._SCENE);
+        private static _LIGHT: BABYLON.Light = new BABYLON.Light("light", SceneElements._SCENE);
+        private static _CAMERA: BABYLON.Camera = new BABYLON.Camera("camera", BABYLON.Vector3.Zero(), SceneElements._SCENE);
+
+        public static get ENGINE(): BABYLON.Engine {
+            return SceneElements._ENGINE;
+        }
+
+        public static get SCENE(): BABYLON.Scene {
+            return SceneElements._SCENE;
+        }
+
+        public static get MESH(): BABYLON.Mesh {
+            return SceneElements._MESH;
+        }
+
+        public static get LIGHT(): BABYLON.Light {
+            return SceneElements._LIGHT;
+        }
+
+        public static get CAMERA(): BABYLON.Camera {
+            return SceneElements._CAMERA;
+        }
+
+        /*
+        * Objects names
+        */
+        private static _MESHES = new Array<string>();
+        private static _LIGHTS = new Array<string>();
+        private static _CAMERAS = new Array<string>();
+        private static _SOUNDS = new Array<string>();
+
+        public static get MESHES(): Array<string> {
+            return SceneElements._MESHES;
+        }
+
+        public static get LIGHTS(): Array<string> {
+            return SceneElements._LIGHTS;
+        }
+
+        public static get CAMERAS(): Array<string> {
+            return SceneElements._CAMERAS;
+        }
+
+        public static get SOUNDS(): Array<string> {
+            return SceneElements._SOUNDS;
+        }
+
+        /*
+        * Properties
+        */
+        private static _MESH_PROPERTIES = new Array<string>();
+        private static _LIGHT_PROPERTIES = new Array<string>();
+        private static _CAMERA_PROPERTIES = new Array<string>();
+        private static _SCENE_PROPERTIES = new Array<string>();
+
+        public static get MESH_PROPERTIES(): Array<string> {
+            return SceneElements._MESH_PROPERTIES;
+        }
+
+        public static get LIGHT_PROPERTIES(): Array<string> {
+            return SceneElements._LIGHT_PROPERTIES;
+        }
+
+        public static get CAMERA_PROPERTIES(): Array<string> {
+            return SceneElements._CAMERA_PROPERTIES;
+        }
+
+        public static get SCENE_PROPERTIES(): Array<string> {
+            return SceneElements._SCENE_PROPERTIES;
+        }
+
+        /*
+        * Types
+        */
+        private static _TYPES = new Array<string>();
+
+        public static get TYPES(): Array<string> {
+            return SceneElements._TYPES;
+        }
+
+        /*
+        * Operators
+        */
+        private static _OPERATORS = new Array<string>();
+
+        public static get OPERATORS(): Array<string> {
+            return SceneElements._OPERATORS;
+        }
+
+        /*
+        * Methods
+        */
+        public static GetInstanceOf(object: Object): string {
+            if (object === null || object === undefined) {
+                return "";
+            }
+            return object.constructor.toString().match(/function (\w*)/)[1];
+        }
+
+        public static TestInstanceOf (object: Object, propertyName: string): boolean {
+            if (object === null || object.constructor === null) {
+                return false;
+            }
+
+            if (propertyName.length > 0 && propertyName[0] === "_")
+                return false;
+
+            var name = SceneElements.GetInstanceOf(object);
+
+            for (var i = 0; i < SceneElements.TYPES.length; i++) {
+                if (name === SceneElements.TYPES[i]) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+    }
+
+    // Functions
+    var specialTypes = [
+        "StandardMaterial"
+    ];
+    SceneElements.MESH.material = new BABYLON.StandardMaterial("material", SceneElements.SCENE);
+
+    var addSpecialType = (object: any, properties: Array<string>, thing: string) => {
+        for (var specialThing in object[thing]) {
+            if (object[thing].hasOwnProperty(specialThing) && SceneElements.TestInstanceOf(object[thing][specialThing], specialThing)) {
+                properties.push(thing + "." + specialThing);
+            }
+        }
+    };
+
+    // Configure types
+    SceneElements.TYPES.push("Color3");
+    SceneElements.TYPES.push("Boolean");
+    SceneElements.TYPES.push("Number");
+    SceneElements.TYPES.push("Vector2");
+    SceneElements.TYPES.push("Vector3");
+    SceneElements.TYPES.push("String");
+
+    // Configure operators
+    SceneElements.OPERATORS.push("IsEqual");
+    SceneElements.OPERATORS.push("IsDifferent");
+    SceneElements.OPERATORS.push("IsGreater");
+    SceneElements.OPERATORS.push("IsLesser");
+
+    // Configure properties
+    for (var thing in SceneElements.MESH) {
+        var instance = SceneElements.GetInstanceOf(SceneElements.MESH[thing]);
+
+        if (SceneElements.MESH.hasOwnProperty(thing)) {
+            if (specialTypes.indexOf(instance) !== -1) {
+                addSpecialType(SceneElements.MESH, SceneElements.MESH_PROPERTIES, thing);
+            }
+            else if (SceneElements.TestInstanceOf(SceneElements.MESH[thing], thing)) {
+                SceneElements.MESH_PROPERTIES.push(thing);
+            }
+        }
+    }
+
+    for (var thing in SceneElements.LIGHT) {
+        if (SceneElements.LIGHT.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.LIGHT[thing], thing)) {
+            SceneElements.LIGHT_PROPERTIES.push(thing);
+        }
+    }
+
+    for (var thing in SceneElements.CAMERA) {
+        if (SceneElements.CAMERA.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.CAMERA[thing], thing)) {
+            SceneElements.CAMERA_PROPERTIES.push(thing);
+        }
+    }
+
+    for (var thing in SceneElements.SCENE) {
+        if (SceneElements.SCENE.hasOwnProperty(thing) && SceneElements.TestInstanceOf(SceneElements.SCENE[thing], thing)) {
+            SceneElements.SCENE_PROPERTIES.push(thing);
+        }
+    }
+
+    /**
+    * Defines an element property
+    */
+    export interface ElementProperty {
+        targetType?: string;
+        text: string;
+        value: string;
+    }
+
+    /**
+    * Defines an element property result
+    */
+    export interface ElementPropertyResult {
+        targetType?: string;
+        value: string;
+    }
+
+    /**
+    * Generic element, has a name, a text to draw, a description
+    * and a list of properties (ElementProperty)
+    */
+    export interface Element {
+        name: string;
+        text: string;
+        properties: Array<ElementProperty>;
+        description: string;
+    }
+
+    /**
+    * Actions Builder elements (triggers, actions & flow controls) that are
+    * arrays of Element
+    */
+    export class Elements {
+        private static _TRIGGERS = new Array<Element>();
+        private static _ACTIONS = new Array<Element>();
+        private static _FLOW_CONTROLS = new Array<Element>();
+
+        public static get TRIGGERS(): Array<Element> {
+            return Elements._TRIGGERS;
+        }
+
+        public static get ACTIONS(): Array<Element> {
+            return Elements._ACTIONS;
+        }
+
+        public static get FLOW_CONTROLS(): Array<Element> {
+            return Elements._FLOW_CONTROLS;
+        }
+
+        public static GetElementFromName(name: string): Element {
+            for (var i = 0; i < Elements.TRIGGERS.length; i++) {
+                if (Elements.TRIGGERS[i].name === name) {
+                    return Elements._TRIGGERS[i];
+                }
+            }
+
+            for (var i = 0; i < Elements.ACTIONS.length; i++) {
+                if (Elements.ACTIONS[i].name === name) {
+                    return Elements._ACTIONS[i];
+                }
+            }
+
+            for (var i = 0; i < Elements.FLOW_CONTROLS.length; i++) {
+                if (Elements.FLOW_CONTROLS[i].name === name) {
+                    return Elements._FLOW_CONTROLS[i];
+                }
+            }
+
+            return null;
+        }
+    }
+
+    // Configure triggers
+    Elements.TRIGGERS.push({ name: "OnPickTrigger", text: "pick", properties: [], description: "When the user picks the edited mesh" });
+    Elements.TRIGGERS.push({ name: "OnLeftPickTrigger", text: "left pick", properties: [], description: "When the user picks the edited mesh using the left click" });
+    Elements.TRIGGERS.push({ name: "OnRightPickTrigger", text: "right pick", properties: [], description: "When the user picks the edited mesh using the right click" });
+    Elements.TRIGGERS.push({ name: "OnCenterPickTrigger", text: "center pick", properties: [], description: "When the user picks the edited mesh using the click of the mouse wheel" });
+    Elements.TRIGGERS.push({ name: "OnPointerOverTrigger", text: "pointer over", properties: [], description: "When the user's mouse is over the edited mesh" });
+    Elements.TRIGGERS.push({ name: "OnPointerOutTrigger", text: "pointer out", properties: [], description: "When the user's mouse is out of the edited mesh" });
+    Elements.TRIGGERS.push({ name: "OnEveryFrameTrigger", text: "every frame", properties: [], description: "This trigger is called each frame (only on scene)" });
+    Elements.TRIGGERS.push({ name: "OnIntersectionEnterTrigger", text: "intersection enter", properties: [{ targetType: "MeshProperties", text: "parameter", value: "Object name?" }], description: "When the edited mesh intersects the another mesh predefined in the options" });
+    Elements.TRIGGERS.push({ name: "OnIntersectionExitTrigger", text: "intersection exit", properties: [{ targetType: "MeshProperties", text: "parameter", value: "Object name?" }], description: "When the edited mesh exits intersection with the another mesh predefined in the options" });
+    Elements.TRIGGERS.push({ name: "OnKeyDownTrigger", text: "key down", properties: [{ targetType: null, text: "parameter", value: "a" }], description: "When the user pressed a key (enter the key character, example: \"r\")" });
+    Elements.TRIGGERS.push({ name: "OnKeyUpTrigger", text: "key up", properties: [{ targetType: null, text: "parameter", value: "a" }], description: "When the user unpressed a key (enter the key character, example: \"p\")" });
+
+    // Configure actions
+    Elements.ACTIONS.push({ name: "SwitchBooleanAction", text: "switch boolean", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }], description: "Switches the boolean value of a given parameter of the target object: true to false, or false to true" });
+    Elements.ACTIONS.push({ name: "SetStateAction", text: "set state", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "value", value: "" }], description: "Sets a new state value for the target object (example: \"off\" or \"on\")" });
+    Elements.ACTIONS.push({ name: "SetValueAction", text: "set value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }], description: "Sets a new value to the specified parameter of the target object (example: position.x to 0.0)" });
+    Elements.ACTIONS.push({ name: "SetParentAction", text: "set parent", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "parent", value: "" }], description: "Sets the new parent of the target object (example: a mesh or a light)" });
+    Elements.ACTIONS.push({ name: "IncrementValueAction", text: "increment value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }], description: "Increments the value of the given parameter of the target object. The value can be negative. (example: increment position.x of 5.0)" });
+    Elements.ACTIONS.push({ name: "PlayAnimationAction", text: "play animation", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "from", value: "0" }, { text: "to", value: "150" }, { text: "loop", value: "false" }], description: "Plays an animation of the target object. Specify the start frame, the end frame and if the animation should loop." });
+    Elements.ACTIONS.push({ name: "StopAnimationAction", text: "stop animation", properties: [{ targetType: "MeshProperties", text: "target", value: "" }], description: "Stops the animations of the target object." });
+    Elements.ACTIONS.push({ name: "DoNothingAction", text: "do nothing", properties: [], description: "Does nothing, can be used to balance/equilibrate the actions graph." });
+    Elements.ACTIONS.push({ name: "InterpolateValueAction", text: "interpolate value", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "0" }, { text: "duration", value: "1000" }, { text: "stopOtherAnimations", value: "false" }], description: "Creates an animation (key frames) that animates the target object by interpolating the given parameter of the target value." });
+    Elements.ACTIONS.push({ name: "PlaySoundAction", text: "play sound", properties: [{ text: "sound", value: "" }], description: "Plays the specified sound." });
+    Elements.ACTIONS.push({ name: "StopSoundAction", text: "stop sound", properties: [{ text: "sound", value: "" }], description: "Stops the specified sound." });
+    Elements.ACTIONS.push({ name: "CombineAction", text: "combine", properties: [], description: "Special action that combines multiple actions. The combined actions are executed at the same time. Drag'n'drop the new actions inside to combine actions." });
+
+    // Configure flow control
+    Elements.FLOW_CONTROLS.push({ name: "ValueCondition", text: "value condition", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "propertyPath", value: "" }, { text: "value", value: "" }, { text: "operator", value: SceneElements.OPERATORS[0] }], description: "A condition checking if a given value is equal, different, lesser or greater than the given parameter of the target object" });
+    Elements.FLOW_CONTROLS.push({ name: "StateCondition", text: "state condition", properties: [{ targetType: "MeshProperties", text: "target", value: "" }, { text: "value", value: "" }], description: "A condition checking if the target object's state is equal to the given state. See \"set state\" action to set a state to an object." });
+    Elements.FLOW_CONTROLS.push({ name: "Hub", text: "hub", properties: [], description: "The hub is internally used by the Combine Action. It allows to add children to the Combine Action" });
+}

+ 370 - 0
Exporters/3ds Max/ActionsBuilder/actionsbuilder.utils.js

@@ -0,0 +1,370 @@
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    var Utils = (function () {
+        function Utils(viewer) {
+            this.copiedStructure = null;
+            this._viewer = viewer;
+        }
+        Utils.prototype.onTestGraph = function () {
+            var _this = this;
+            if (this._viewer.root.children.length === 0) {
+                alert("Please add at least a Trigger and an Action to test the graph");
+            }
+            var onTestTarget = function (targetType, target) {
+                var targetExists = false;
+                var array = _this._viewer.parameters._getTargetFromType(targetType);
+                if (array === null) {
+                    return targetExists;
+                }
+                for (var i = 0; i < array.length; i++) {
+                    if (array[i] === target) {
+                        targetExists = true;
+                        break;
+                    }
+                }
+                return targetExists;
+            };
+            var onNodeError = function (action) {
+                var node = action.node;
+                node.rect.attr("fill", Raphael.rgb(255, 0, 0));
+                return false;
+            };
+            var onTestAction = function (action) {
+                console.log("Testing " + action.name);
+                if (action.combineArray !== null) {
+                    var foundError = false;
+                    for (var i = 0; i < action.combineArray.length; i++) {
+                        if (!onTestAction(action.combineArray[i])) {
+                            foundError = true;
+                        }
+                    }
+                    if (foundError) {
+                        return false;
+                    }
+                }
+                else {
+                    var properties = action.properties;
+                    var propertiesResults = action.propertiesResults;
+                    if (properties !== null) {
+                        var object = null;
+                        var propertyPath = null;
+                        for (var i = 0; i < properties.length; i++) {
+                            if (properties[i].text === "target" || properties[i].text === "parent") {
+                                object = _this._viewer.parameters._getObjectFromType(properties[i].targetType);
+                                var targetExists = onTestTarget(propertiesResults[i].targetType, propertiesResults[i].value);
+                                if (!targetExists) {
+                                    return onNodeError(action);
+                                }
+                            }
+                            else if (properties[i].text === "propertyPath") {
+                                var property = propertiesResults[i].value;
+                                var effectiveProperty = object;
+                                var p = property.split(".");
+                                for (var j = 0; j < p.length && effectiveProperty !== undefined; j++) {
+                                    effectiveProperty = effectiveProperty[p[j]];
+                                }
+                                if (effectiveProperty === undefined) {
+                                    return onNodeError(action);
+                                }
+                                else {
+                                    propertyPath = effectiveProperty;
+                                }
+                            }
+                            else if (properties[i].text == "value" && propertyPath != null) {
+                                var value = propertiesResults[i].value;
+                                if (!isNaN(propertyPath)) {
+                                    var num = parseFloat(value);
+                                    if (isNaN(num) || value === "") {
+                                        return onNodeError(action);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    var foundError = false;
+                    for (var i = 0; i < action.children.length; i++) {
+                        if (!onTestAction(action.children[i])) {
+                            foundError = true;
+                        }
+                    }
+                    return !foundError;
+                }
+            };
+            var root = this._viewer.root;
+            var foundError = false;
+            for (var i = 0; i < root.children.length; i++) {
+                var trigger = root.children[i];
+                var properties = trigger.properties;
+                if (properties !== null && properties.length > 0) {
+                    var parameter = trigger.propertiesResults[0].value;
+                    if (properties[0].targetType !== null) {
+                        if (!onTestTarget("MeshProperties", parameter)) {
+                            foundError = onNodeError(trigger);
+                        }
+                    }
+                    else {
+                        if (!parameter.match(/[a-z]/)) {
+                            foundError = onNodeError(trigger);
+                        }
+                    }
+                }
+                for (var j = 0; j < trigger.children.length; j++) {
+                    var child = trigger.children[j];
+                    var result = onTestAction(child);
+                    if (!result) {
+                        foundError = true;
+                    }
+                }
+            }
+            if (foundError) {
+                alert("Found error(s). the red nodes contain the error.");
+            }
+            else {
+                alert("No error found.");
+            }
+        };
+        Utils.prototype.onReduceAll = function (forceExpand) {
+            if (forceExpand === void 0) { forceExpand = false; }
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            var action = this._viewer.selectedNode;
+            if (action.combineArray !== null) {
+                for (var i = 0; i < action.combineArray.length; i++) {
+                    this._viewer.selectedNode = action.combineArray[i];
+                    this.onReduce(forceExpand, !forceExpand);
+                }
+            }
+            else {
+                this.onReduce(forceExpand, !forceExpand);
+            }
+            for (var i = 0; i < action.children.length; i++) {
+                this._viewer.selectedNode = action.children[i];
+                this.onReduceAll(forceExpand);
+            }
+        };
+        Utils.prototype.onReduce = function (forceExpand, forceReduce) {
+            if (forceExpand === void 0) { forceExpand = false; }
+            if (forceReduce === void 0) { forceReduce = false; }
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            var node = this._viewer.selectedNode.node;
+            node.rect.stop(node.rect.animation);
+            if (forceExpand === true) {
+                node.minimized = false;
+            }
+            else if (forceReduce === true) {
+                node.minimized = true;
+            }
+            else {
+                node.minimized = !node.minimized;
+            }
+            if (node.minimized) {
+                node.text.hide();
+                node.rect.attr("width", ActionsBuilder.Viewer.NODE_MINIMIZED_WIDTH * this._viewer.zoom);
+            }
+            else {
+                node.text.show();
+                node.rect.attr("width", ActionsBuilder.Viewer.NODE_WIDTH * this._viewer.zoom);
+            }
+        };
+        Utils.prototype.onDetachAction = function (forceDetach, forceAttach) {
+            var _this = this;
+            if (forceDetach === void 0) { forceDetach = false; }
+            if (forceAttach === void 0) { forceAttach = false; }
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            var action = this._viewer.selectedNode;
+            if (forceDetach === true) {
+                action.node.detached = true;
+            }
+            else if (forceAttach === true) {
+                action.node.detached = false;
+            }
+            else {
+                action.node.detached = !action.node.detached;
+            }
+            var onSetColor = function (root, detached) {
+                var rootNode = root.node;
+                rootNode.rect.attr("fill", _this._viewer.getNodeColor(root.type, detached));
+                if (root.combineArray !== null) {
+                    for (var i = 0; i < root.combineArray.length; i++) {
+                        var combineNode = root.combineArray[i].node;
+                        combineNode.rect.attr("fill", _this._viewer.getNodeColor(root.combineArray[i].type, detached));
+                    }
+                }
+                for (var i = 0; i < root.children.length; i++) {
+                    onSetColor(root.children[i], detached);
+                }
+            };
+            onSetColor(action, action.node.detached);
+        };
+        Utils.prototype.onRemoveNode = function () {
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            var action = this._viewer.selectedNode;
+            var parent = action.parent;
+            if (action.type === ActionsBuilder.Type.TRIGGER) {
+                this.onRemoveBranch();
+                return;
+            }
+            if (action.type === ActionsBuilder.Type.FLOW_CONTROL && parent !== null && parent.combineArray !== null) {
+                action = parent;
+                parent = action.parent;
+            }
+            if (parent !== null && parent.combineArray !== null) {
+                parent.removeCombinedAction(action);
+                if (parent.combineArray.length === 0) {
+                    parent.node.text.attr("text", "combine");
+                }
+            }
+            else {
+                if (action.combineArray !== null) {
+                    action.removeChild(action.hub);
+                }
+                action.parent.removeChild(action);
+            }
+            if (action.combineArray !== null) {
+                this._viewer.removeAction(action.hub, false);
+            }
+            this._viewer.removeAction(action, false);
+            this._viewer.update();
+            this._viewer.parameters.clearParameters();
+            this._viewer.selectedNode = null;
+        };
+        Utils.prototype.onRemoveBranch = function () {
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            if (this._viewer.selectedNode === this._viewer.root) {
+                alert("Cannot remove the root node");
+                return;
+            }
+            var action = this._viewer.selectedNode;
+            var parent = action.parent;
+            if (action.parent !== null && action.parent.combineArray !== null) {
+                action = parent;
+                parent = action.parent;
+            }
+            if (action.combineArray !== null) {
+                action.removeChild(action.hub);
+            }
+            action.parent.removeChild(action);
+            this._viewer.removeAction(action, true);
+            this._viewer.update();
+            this._viewer.parameters.clearParameters();
+            this._viewer.selectedNode = null;
+        };
+        Utils.prototype.onCopyStructure = function () {
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            var structure = this.createJSON(this._viewer.selectedNode);
+            var asText = JSON.stringify(structure);
+            if (window.clipboardData !== undefined) {
+                window.clipboardData.setData("text", asText);
+            }
+            else {
+                this.copiedStructure = asText;
+            }
+        };
+        Utils.prototype.onPasteStructure = function () {
+            if (this._viewer.selectedNode === null) {
+                return;
+            }
+            var asText = (window.clipboardData !== undefined) ? window.clipboardData.getData("text") : this.copiedStructure;
+            var isJson = asText.length > 0 && asText[0] == "{" && asText[asText.length - 1] == "}";
+            var structure = JSON.parse(asText);
+            var action = this._viewer.selectedNode;
+            if (structure.type === ActionsBuilder.Type.TRIGGER && action !== this._viewer.root) {
+                alert("You can't paste a trigger if the selected node isn't the root object");
+                return;
+            }
+            if (structure.type !== ActionsBuilder.Type.TRIGGER && action === this._viewer.root) {
+                alert("You can't paste an action or condition if the selected node is the root object");
+                return;
+            }
+            this.loadFromJSON(structure, action);
+            this._viewer.update();
+        };
+        Utils.prototype.loadFromJSON = function (graph, startAction) {
+            var _this = this;
+            if (startAction === null) {
+                for (var i = 0; i < this._viewer.root.children.length; i++) {
+                    this._viewer.removeAction(this._viewer.root.children[i], true);
+                }
+                this._viewer.root.clearChildren();
+            }
+            var load = function (root, parent, detached, combine) {
+                if (parent === null) {
+                    parent = _this._viewer.root;
+                }
+                var newAction = null;
+                if (root.type !== ActionsBuilder.Type.OBJECT && root.type !== ActionsBuilder.Type.SCENE) {
+                    var action = _this._viewer.addAction(parent, root.type, ActionsBuilder.Elements.GetElementFromName(root.name));
+                    for (var i = 0; i < root.properties.length; i++) {
+                        var targetType = root.properties[i].targetType;
+                        if (targetType === undefined) {
+                            targetType = "MeshProperties";
+                        }
+                        action.propertiesResults[i] = { value: root.properties[i].value, targetType: targetType };
+                    }
+                    var node = action.node;
+                    node.detached = root.detached;
+                    if (detached) {
+                        node.rect.attr("fill", _this._viewer.getNodeColor(action.type, detached));
+                    }
+                    if (root.combine !== undefined) {
+                        for (var i = 0; i < root.combine.length; i++) {
+                            load(root.combine[i], action, detached, true);
+                        }
+                    }
+                    if (!combine) {
+                        parent = parent.children[parent.children.length - 1];
+                    }
+                }
+                for (var i = 0; i < root.children.length; i++) {
+                    load(root.children[i], newAction !== null && newAction.combineArray !== null ? newAction.hub : parent, root.detached, false);
+                }
+            };
+            load(graph, startAction, false, false);
+            this._viewer.update();
+        };
+        Utils.prototype.createJSON = function (root) {
+            var action = {
+                type: root.type,
+                name: root.name,
+                detached: root.node.detached,
+                children: new Array(),
+                combine: new Array(),
+                properties: new Array()
+            };
+            for (var i = 0; i < root.properties.length; i++) {
+                action.properties.push({
+                    name: root.properties[i].text,
+                    value: root.propertiesResults[i].value,
+                    targetType: root.propertiesResults[i].targetType
+                });
+            }
+            if (root.combineArray !== null) {
+                for (var i = 0; i < root.combineArray.length; i++) {
+                    var combinedAction = root.combineArray[i];
+                    action.combine.push(this.createJSON(combinedAction));
+                }
+                root = root.children[0];
+            }
+            for (var i = 0; i < root.children.length; i++) {
+                action.children.push(this.createJSON(root.children[i]));
+            }
+            return action;
+        };
+        Utils.prototype.setElementVisible = function (element, visible) {
+            element.style.display = visible ? "block" : "none";
+        };
+        return Utils;
+    })();
+    ActionsBuilder.Utils = Utils;
+})(ActionsBuilder || (ActionsBuilder = {}));

文件差異過大導致無法顯示
+ 526 - 526
Exporters/3ds Max/ActionsBuilder/actionsbuilder.utils.ts


+ 539 - 0
Exporters/3ds Max/ActionsBuilder/actionsbuilder.viewer.js

@@ -0,0 +1,539 @@
+var ActionsBuilder;
+(function (ActionsBuilder) {
+    var Viewer = (function () {
+        function Viewer(type) {
+            var _this = this;
+            this.objectName = "Unnamed Object";
+            this.zoom = 1.0;
+            this._firstUpdate = true;
+            this.viewerContainer = document.getElementById("GraphContainerID");
+            this.viewerElement = document.getElementById("GraphElementID");
+            this.paper = Raphael("GraphElementID", screen.width, screen.height);
+            this.root = this.addAction(null, type, { name: this.objectName, text: this.objectName, properties: [], description: "" });
+            this.selectedNode = null;
+            window.addEventListener("resize", function (event) {
+                _this.onResize(event);
+            });
+            window.addEventListener("mousemove", function (event) {
+                _this.onMove(event);
+            });
+            this.paper.canvas.addEventListener("click", function (event) {
+                _this.onClick(event);
+            });
+            this._toolbar = new ActionsBuilder.Toolbar(this);
+            this._contextMenu = new ActionsBuilder.ContextMenu(this);
+            this.parameters = new ActionsBuilder.Parameters(this);
+            this.utils = new ActionsBuilder.Utils(this);
+            this.parameters.parametersHelpElement.textContent = Viewer._DEFAULT_INFO_MESSAGE;
+            this.onResize(null);
+        }
+        Object.defineProperty(Viewer, "NODE_WIDTH", {
+            get: function () {
+                return Viewer._NODE_WIDTH;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Viewer, "NODE_HEIGHT", {
+            get: function () {
+                return Viewer._NODE_HEIGHT;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Viewer, "NODE_MINIMIZED_WIDTH", {
+            get: function () {
+                return Viewer._NODE_MINIMIZE_WIDTH;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(Viewer, "VERTICAL_OFFSET", {
+            get: function () {
+                return Viewer._VERTICAL_OFFSET;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Viewer.prototype.onResize = function (event) {
+            var tools = document.getElementById("ToolsButtonsID");
+            this.viewerContainer.style.height = window.innerHeight - tools.getBoundingClientRect().height - 25 - 50 + "px";
+            this.viewerElement.style.height = window.innerHeight - tools.getBoundingClientRect().height - 25 - 50 + "px";
+            this.parameters.onResize();
+            this._toolbar.onResize();
+            if (this.paper.height < window.innerHeight) {
+                this.paper.setSize(this.paper.width, window.innerHeight);
+            }
+            if (this._firstUpdate) {
+                this.viewerElement.scrollLeft = ((this.viewerElement.scrollWidth / 2) - (this.viewerElement.getBoundingClientRect().width / 2));
+                this._firstUpdate = false;
+            }
+        };
+        Viewer.prototype.onMove = function (event) {
+            this.mousex = event.clientX - this.paper.canvas.getBoundingClientRect().left;
+            this.mousey = event.clientY - this.paper.canvas.getBoundingClientRect().top;
+        };
+        Viewer.prototype.onClick = function (event) {
+            if (this._contextMenu.showing) {
+                return;
+            }
+            if (this.selectedNode !== null) {
+                var node = this.selectedNode.node;
+                node.rect.attr("fill", this.getNodeColor(this.selectedNode.type, node.detached));
+            }
+            var result = this.traverseGraph(null, this.mousex, this.mousey, true);
+            if (result.hit) {
+                this.selectedNode = result.action;
+                var node = this.selectedNode.node;
+                node.rect.attr("fill", this.getSelectedNodeColor(this.selectedNode.type, node.detached));
+            }
+            else {
+                this.selectedNode = null;
+                this.parameters.clearParameters();
+                this.parameters.parametersHelpElement.textContent = Viewer._DEFAULT_INFO_MESSAGE;
+            }
+        };
+        Viewer.prototype.setColorTheme = function (color) {
+            this.paper.canvas.style.background = color;
+        };
+        Viewer.prototype.getNodeColor = function (type, detached) {
+            if (detached) {
+                return Raphael.rgb(96, 122, 14);
+            }
+            switch (type) {
+                case ActionsBuilder.Type.TRIGGER:
+                    return Raphael.rgb(133, 154, 185);
+                    break;
+                case ActionsBuilder.Type.ACTION:
+                    return Raphael.rgb(182, 185, 132);
+                    break;
+                case ActionsBuilder.Type.FLOW_CONTROL:
+                    return Raphael.rgb(185, 132, 140);
+                    break;
+                case ActionsBuilder.Type.OBJECT:
+                case ActionsBuilder.Type.SCENE:
+                    return Raphael.rgb(255, 255, 255);
+                    break;
+                default: break;
+            }
+            return null;
+        };
+        Viewer.prototype.getSelectedNodeColor = function (type, detached) {
+            if (detached) {
+                return Raphael.rgb(96, 122, 14);
+            }
+            switch (type) {
+                case ActionsBuilder.Type.TRIGGER:
+                    return Raphael.rgb(41, 129, 255);
+                    break;
+                case ActionsBuilder.Type.ACTION:
+                    return Raphael.rgb(255, 220, 42);
+                    break;
+                case ActionsBuilder.Type.FLOW_CONTROL:
+                    return Raphael.rgb(255, 41, 53);
+                    break;
+                case ActionsBuilder.Type.OBJECT:
+                case ActionsBuilder.Type.SCENE:
+                    return Raphael.rgb(255, 255, 255);
+                    break;
+                default: break;
+            }
+            return null;
+        };
+        Viewer.prototype.removeAction = function (action, removeChildren) {
+            if (action.parent !== null && action.parent.hub === action) {
+                this.removeAction(action.parent, false);
+                return;
+            }
+            this.removeNode(action.node);
+            if (action.combineArray !== null) {
+                this.removeNode(action.hub.node);
+                for (var i = 0; i < action.combineArray.length; i++) {
+                    this.removeNode(action.combineArray[i].node);
+                }
+                action.combineArray.length = 0;
+            }
+            if (removeChildren) {
+                for (var i = 0; i < action.children.length; i++) {
+                    this.removeAction(action.children[i], removeChildren);
+                }
+                action.clearChildren();
+            }
+            else {
+                for (var i = 0; i < action.children.length; i++) {
+                    action.parent.addChild(action.children[i]);
+                    action.children[i].parent = action.parent;
+                }
+            }
+        };
+        Viewer.prototype.removeNode = function (node) {
+            node.rect.remove();
+            node.text.remove();
+            if (node.line !== null) {
+                node.line.remove();
+            }
+        };
+        Viewer.prototype.update = function () {
+            var _this = this;
+            this._setActionPosition(this.root, (this.paper.width / 2) - (Viewer.NODE_WIDTH / 2) * this.zoom, 10);
+            var onSetNodeSize = function (node) {
+                node.rect.attr("width", node.minimized ? Viewer.NODE_MINIMIZED_WIDTH : Viewer.NODE_WIDTH * _this.zoom);
+                node.rect.attr("height", Viewer.NODE_HEIGHT * _this.zoom);
+                node.text.attr("font-size", 11 * _this.zoom);
+            };
+            var onSetPositionPass = function (action, yPosition) {
+                var node = action.node;
+                var parent = action.parent !== null ? action.parent : null;
+                if (action.combineArray !== null) {
+                    for (var i = 0; i < action.combineArray.length; i++) {
+                        var combinedNode = action.combineArray[i].node;
+                        onSetNodeSize(combinedNode);
+                    }
+                }
+                onSetNodeSize(node);
+                if (parent) {
+                    var parentx = parent.node.rect.attr("x");
+                    if (parent.combineArray !== null && parent.combineArray.length > 1) {
+                        parentx += parent.node.rect.attr("width") / 2;
+                    }
+                    _this._setActionPosition(action, parentx, yPosition);
+                    _this._setActionLine(action);
+                }
+                var totalSize = 0;
+                for (var i = 0; i < action.children.length; i++) {
+                    var childNode = action.children[i].node;
+                    totalSize += childNode.rect.attr("width");
+                }
+                var nodeWidth = node.rect.attr("width");
+                var startingPositionX = node.rect.attr("x");
+                for (var i = 0; i < action.children.length; i++) {
+                    var childAction = action.children[i];
+                    var childNode = childAction.node;
+                    var newPositionX = startingPositionX;
+                    if (childAction.combineArray !== null && childAction.combineArray.length > 1) {
+                        newPositionX -= (childNode.rect.attr("width") / 2) - nodeWidth / 2;
+                    }
+                    var newPositionY = yPosition + Viewer.VERTICAL_OFFSET * _this.zoom;
+                    onSetPositionPass(childAction, newPositionY);
+                    _this._setActionPosition(childAction, newPositionX, newPositionY);
+                    _this._setActionLine(childAction);
+                }
+            };
+            onSetPositionPass(this.root, 10 * this.zoom);
+            var onGetSizePass = function (action, maxSize) {
+                var mySize = 0;
+                if (action.combineArray !== null) {
+                    for (var i = 0; i < action.combineArray.length; i++) {
+                        mySize += action.combineArray[i].node.rect.attr("width");
+                    }
+                }
+                else {
+                    mySize = action.node.rect.attr("width");
+                }
+                if (mySize > maxSize) {
+                    maxSize = mySize;
+                }
+                for (var i = 0; i < action.children.length; i++) {
+                    maxSize = onGetSizePass(action.children[i], maxSize);
+                }
+                return maxSize;
+            };
+            var onResizeCanvas = function (action) {
+                var node = action.node;
+                var nodex = node.rect.attr("x");
+                var nodey = node.rect.attr("y");
+                if (nodex < 0 || nodex > _this.paper.width) {
+                    _this.paper.setSize(_this.paper.width + 1000, _this.paper.height);
+                    _this._setActionPosition(_this.root, (_this.paper.width / 2) - (Viewer.NODE_WIDTH / 2) * _this.zoom, 10);
+                }
+                if (nodey > _this.paper.height) {
+                    _this.paper.setSize(_this.paper.width, _this.paper.height + 1000);
+                    _this._setActionPosition(_this.root, (_this.paper.width / 2) - (Viewer.NODE_WIDTH / 2) * _this.zoom, 10);
+                }
+            };
+            var widths = new Array();
+            for (var i = 0; i < this.root.children.length; i++) {
+                var trigger = this.root.children[i];
+                var triggerResult = { triggerWidth: onGetSizePass(trigger, 0), childrenWidths: new Array() };
+                if (trigger.children.length > 0) {
+                    triggerResult.triggerWidth = 0;
+                }
+                for (var j = 0; j < trigger.children.length; j++) {
+                    var actionWidth = onGetSizePass(trigger.children[j], 0);
+                    triggerResult.triggerWidth += actionWidth + 15;
+                    triggerResult.childrenWidths.push({
+                        triggerWidth: actionWidth,
+                        childrenWidths: null
+                    });
+                }
+                widths.push(triggerResult);
+            }
+            var onSetNodePosition = function (action, widthArray, isChild) {
+                var actionsCount = action.children.length;
+                var actionsMiddle = actionsCount % 2;
+                var actionsHasMiddle = actionsMiddle !== 0;
+                var actionsLeftOffset = 0;
+                var actionsRightOffset = 0;
+                var actionWidth = action.node.rect.attr("width");
+                if (actionsHasMiddle && actionsCount > 1) {
+                    var middle = Math.floor(actionsCount / 2);
+                    actionsLeftOffset += widthArray[middle].triggerWidth / 2;
+                    actionsRightOffset += widthArray[middle].triggerWidth / 2;
+                }
+                var leftStart = actionsHasMiddle ? Math.floor(actionsCount / 2) - 1 : (actionsCount / 2) - 1;
+                for (var i = leftStart; i >= 0; i--) {
+                    var child = action.children[i];
+                    var node = child.node;
+                    var width = (widthArray[i].triggerWidth) + 15;
+                    _this._setActionPosition(action.children[i], node.rect.attr("x") - actionsLeftOffset - (width / 2), node.rect.attr("y"));
+                    _this._setActionLine(child);
+                    onResizeCanvas(child);
+                    actionsLeftOffset += width;
+                }
+                var rightStart = actionsHasMiddle ? Math.round(actionsCount / 2) : actionsCount / 2;
+                for (var i = rightStart; i < actionsCount; i++) {
+                    var child = action.children[i];
+                    var node = child.node;
+                    var width = (widthArray[i].triggerWidth) + 15;
+                    _this._setActionPosition(action.children[i], node.rect.attr("x") + actionsRightOffset + (width / 2), node.rect.attr("y"));
+                    _this._setActionLine(child);
+                    onResizeCanvas(child);
+                    actionsRightOffset += width;
+                }
+            };
+            onSetNodePosition(this.root, widths, false);
+            for (var i = 0; i < this.root.children.length; i++) {
+                onSetNodePosition(this.root.children[i], widths[i].childrenWidths, true);
+            }
+        };
+        Viewer.prototype.addAction = function (parent, type, element) {
+            var node = this._createNode(element.text, type, parent === null);
+            var action = new ActionsBuilder.Action(node);
+            if (element.name === "CombineAction") {
+                action.combineArray = new Array();
+                var hubElement = ActionsBuilder.Elements.FLOW_CONTROLS[ActionsBuilder.Elements.FLOW_CONTROLS.length - 1];
+                var hub = this.addAction(action, ActionsBuilder.Type.FLOW_CONTROL, hubElement);
+                action.hub = hub;
+                action.addChild(hub);
+                this._createActionAnimation(hub);
+            }
+            action.name = element.name;
+            action.properties = element.properties;
+            action.type = type;
+            for (var i = 0; i < action.properties.length; i++) {
+                action.propertiesResults.push({ targetType: action.properties[i].targetType, value: action.properties[i].value });
+            }
+            if (action.properties !== null && action.properties.length > 0) {
+                if (action.properties[0].text === "target") {
+                    action.propertiesResults[0].value = this.objectName;
+                }
+            }
+            if (parent !== null) {
+                if (parent.combineArray === null) {
+                    parent.addChild(action);
+                }
+                else if (parent.combineArray !== null && action.name !== "Hub") {
+                    parent.combineArray.push(action);
+                    action.parent = parent;
+                    action.combineAction = parent;
+                    parent.node.text.attr("text", "");
+                }
+            }
+            this._createActionAnimation(action);
+            return action;
+        };
+        Viewer.prototype.traverseGraph = function (start, x, y, traverseCombine) {
+            if (start === null)
+                start = this.root;
+            var result = { action: start, hit: true };
+            if (start.node.isPointInside(x, y)) {
+                return result;
+            }
+            for (var i = 0; i < start.children.length; i++) {
+                var action = start.children[i];
+                if (action.node.isPointInside(x, y)) {
+                    result.hit = true;
+                    result.action = start.children[i];
+                    if (traverseCombine && action.combineArray !== null) {
+                        for (var j = 0; j < action.combineArray.length; j++) {
+                            if (action.combineArray[j].node.isPointInside(x, y)) {
+                                result.action = action.combineArray[j];
+                                break;
+                            }
+                        }
+                    }
+                    return result;
+                }
+                result = this.traverseGraph(action, x, y, traverseCombine);
+                if (result.hit) {
+                    return result;
+                }
+            }
+            result.hit = false;
+            result.action = null;
+            return result;
+        };
+        Viewer.prototype._setActionPosition = function (action, x, y) {
+            var node = action.node;
+            var offsetx = node.rect.attr("x") - x;
+            var parent = action.parent;
+            if (parent !== null && parent.combineArray !== null && parent.combineArray.length > 1) {
+                var parentNode = parent.node;
+                x = parentNode.rect.attr("x") + (parent.node.rect.attr("width") / 2) - (node.rect.attr("width") / 2);
+            }
+            node.rect.attr("x", x);
+            node.rect.attr("y", y);
+            var textBBox = node.text.getBBox();
+            var textWidth = 0;
+            if (textBBox !== null && textBBox !== undefined) {
+                textWidth = textBBox.width;
+            }
+            node.text.attr("x", x + node.rect.attr("width") / 2 - textWidth / 2);
+            node.text.attr("y", y + node.rect.attr("height") / 2);
+            if (action.combineArray !== null && action.combineArray.length > 0) {
+                var length = 0;
+                for (var i = 0; i < action.combineArray.length; i++) {
+                    var combinedAction = action.combineArray[i];
+                    var combinedNode = combinedAction.node;
+                    combinedNode.rect.attr("x", node.rect.attr("x") + length);
+                    combinedNode.rect.attr("y", node.rect.attr("y"));
+                    textBBox = combinedNode.text.getBBox();
+                    if (textBBox !== null) {
+                        textWidth = textBBox.width;
+                    }
+                    combinedNode.text.attr("x", combinedNode.rect.attr("x") + combinedNode.rect.attr("width") / 2 - textWidth / 2);
+                    combinedNode.text.attr("y", y + combinedNode.rect.attr("height") / 2);
+                    length += combinedNode.rect.attr("width");
+                }
+                node.rect.attr("width", length);
+            }
+            for (var i = 0; i < action.children.length; i++) {
+                var child = action.children[i];
+                this._setActionPosition(child, child.node.rect.attr("x") - offsetx, y + Viewer.VERTICAL_OFFSET * this.zoom);
+                this._setActionLine(child);
+            }
+        };
+        Viewer.prototype._setActionLine = function (action) {
+            if (action.node.line === null) {
+                return;
+            }
+            var node = action.node;
+            var nodex = node.rect.attr("x");
+            var nodey = node.rect.attr("y");
+            var nodeWidth = node.rect.attr("width");
+            var nodeHeight = node.rect.attr("height");
+            var parent = action.parent.node;
+            var parentx = parent.rect.attr("x");
+            var parenty = parent.rect.attr("y");
+            var parentWidth = parent.rect.attr("width");
+            var parentHeight = parent.rect.attr("height");
+            if (node.detached) {
+                node.line.attr("path", ["M", nodex, nodey, "L", nodex, nodey]);
+                return;
+            }
+            var line1x = nodex + (nodeWidth / 2);
+            var line1y = nodey;
+            var line2y = line1y - (line1y - parenty - parentHeight) / 2;
+            var line3x = parentx + (parentWidth / 2);
+            var line4y = parenty + parentHeight;
+            node.line.attr("path", ["M", line1x, line1y, "L", line1x, line2y, "L", line3x, line2y, "L", line3x, line4y]);
+        };
+        Viewer.prototype._createNode = function (text, type, noLine) {
+            var node = new ActionsBuilder.Node();
+            var color = this.getNodeColor(type, false);
+            node.rect = this.paper.rect(20, 20, Viewer.NODE_WIDTH, Viewer.NODE_HEIGHT, 0);
+            node.rect.attr("fill", color);
+            node.text = this.paper.text(20, 20, text);
+            node.text.attr("font-size", 11);
+            node.text.attr("text-anchor", "start");
+            node.text.attr("font-family", "Sinkin Sans Light");
+            if (!noLine) {
+                node.line = this.paper.path("");
+                node.line.attr("stroke", color);
+            }
+            return node;
+        };
+        Viewer.prototype._createActionAnimation = function (action) {
+            var _this = this;
+            var node = action.node;
+            var finished = true;
+            var nodex = 0;
+            var nodey = 0;
+            var onMove = function (dx, dy, x, y) { };
+            var onStart = function (x, y, event) {
+                if (node.minimized) {
+                    return;
+                }
+                if (finished) {
+                    nodex = node.rect.attr("x");
+                    nodey = node.rect.attr("y");
+                }
+                finished = false;
+                node.rect.animate({
+                    x: node.rect.attr("x") - 10,
+                    y: node.rect.attr("y"),
+                    width: (Viewer.NODE_WIDTH + 20) * _this.zoom,
+                    height: (Viewer.NODE_HEIGHT + 10) * _this.zoom,
+                    opacity: 0.25
+                }, 500, ">");
+            };
+            var onEnd = function (event) {
+                if (!node.minimized) {
+                    node.rect.animate({
+                        x: nodex,
+                        y: nodey,
+                        width: Viewer.NODE_WIDTH * _this.zoom,
+                        height: Viewer.NODE_HEIGHT * _this.zoom,
+                        opacity: 1.0
+                    }, 500, ">", function () { finished = true; });
+                }
+                var dragResult = _this.traverseGraph(null, _this.mousex, _this.mousey, true);
+                if (dragResult.hit && dragResult.action === action || !dragResult.hit) {
+                    _this.parameters.createParameters(action);
+                }
+                else {
+                    if (dragResult.action.children.length > 0 && action.type !== ActionsBuilder.Type.TRIGGER) {
+                        return;
+                    }
+                    if (action.type === ActionsBuilder.Type.TRIGGER && dragResult.action !== _this.root) {
+                        return;
+                    }
+                    if (action.type === ActionsBuilder.Type.ACTION && dragResult.action === _this.root) {
+                        return;
+                    }
+                    if (action.type === ActionsBuilder.Type.FLOW_CONTROL && (dragResult.action === _this.root || dragResult.action.type === ActionsBuilder.Type.FLOW_CONTROL)) {
+                        return;
+                    }
+                    if (action === dragResult.action.parent) {
+                        return;
+                    }
+                    if (action.parent !== null && action.parent.combineArray !== null) {
+                        return;
+                    }
+                    node.rect.stop(node.rect.animation);
+                    node.text.stop(node.text.animation);
+                    node.rect.undrag();
+                    node.text.undrag();
+                    node.rect.attr("opacity", 1.0);
+                    node.rect.attr("width", Viewer.NODE_WIDTH);
+                    node.rect.attr("height", Viewer.NODE_HEIGHT);
+                    if (action.parent !== null) {
+                        action.parent.removeChild(action);
+                        dragResult.action.addChild(action);
+                        _this.update();
+                        _this._createActionAnimation(action);
+                    }
+                }
+            };
+            node.rect.drag(onMove, onStart, onEnd);
+            node.text.drag(onMove, onStart, onEnd);
+        };
+        Viewer._NODE_WIDTH = 150;
+        Viewer._NODE_HEIGHT = 25;
+        Viewer._NODE_MINIMIZE_WIDTH = 50;
+        Viewer._VERTICAL_OFFSET = 70;
+        Viewer._DEFAULT_INFO_MESSAGE = "Select or add a node to customize actions";
+        return Viewer;
+    })();
+    ActionsBuilder.Viewer = Viewer;
+})(ActionsBuilder || (ActionsBuilder = {}));

文件差異過大導致無法顯示
+ 772 - 772
Exporters/3ds Max/ActionsBuilder/actionsbuilder.viewer.ts


+ 42 - 42
Exporters/3ds Max/ActionsBuilder/gulpfile.js

@@ -1,42 +1,42 @@
-var gulp = require('gulp');
-var ts = require('gulp-typescript');
-
-var files = [
-    // Files
-    // Equivalent to "./*.ts",
-    "actionsbuilder.actionNode.ts",
-    "actionsbuilder.contextMenu.ts",
-	"actionsbuilder.list.ts",
-    "actionsbuilder.main.ts",
-    "actionsbuilder.parameters.ts",
-    "actionsbuilder.toolbar.ts",
-    "actionsbuilder.ts",
-    "actionsbuilder.utils.ts",
-    "actionsbuilder.viewer.ts",
-    // References
-    "raphaeljs.d.ts",
-    "../../dist/*.d.ts",
-    "../..external references/**/*.d.ts"
-];
-
-gulp.task("default", function () {
-    var result = gulp.src(files)
-		.pipe(ts({
-            target: "ES5",
-		    out: "actionsbuilder.max.js" // Merge
-		}));
-    return result.js.pipe(gulp.dest("./Sources/"));
-});
-
-gulp.task("debug", function () {
-    var result = gulp.src(files)
-		.pipe(ts({
-		    target: "ES5",
-            outDir: "./Sources/"
-		}));
-    return result.js.pipe(gulp.dest("./Sources/"));
-});
-
-gulp.task("watch", function () {
-    gulp.watch(files, ["default"]);
-});
+/// <binding />
+var gulp = require('gulp');
+var ts = require('gulp-typescript');
+
+var files = [
+    // Files
+    // Equivalent to "./*.ts",
+    "actionsbuilder.actionNode.ts",
+    "actionsbuilder.contextMenu.ts",
+	"actionsbuilder.list.ts",
+    "actionsbuilder.main.ts",
+    "actionsbuilder.parameters.ts",
+    "actionsbuilder.toolbar.ts",
+    "actionsbuilder.ts",
+    "actionsbuilder.utils.ts",
+    "actionsbuilder.viewer.ts",
+    // References
+    "raphaeljs.d.ts",
+    "../../../dist/preview release/babylon.d.ts"
+];
+
+gulp.task("default", function () {
+    var result = gulp.src(files)
+		.pipe(ts({
+            target: "ES5",
+		    out: "actionsbuilder.max.js" // Merge
+		}));
+    return result.js.pipe(gulp.dest("./Sources/"));
+});
+
+gulp.task("debug", function () {
+    var result = gulp.src(files)
+		.pipe(ts({
+		    target: "ES5",
+            outDir: "./Sources/"
+		}));
+    return result.js.pipe(gulp.dest("./Sources/"));
+});
+
+gulp.task("watch", function () {
+    gulp.watch(files, ["default"]);
+});

+ 10 - 11
Exporters/3ds Max/ActionsBuilder/package.json

@@ -1,11 +1,10 @@
-{
-  "name": "BabylonJSActionsBuilder",
-  "version": "2.2.0",
-  "description": "",
-  "main": "",
-  "devDependencies": {
-    "gulp": "^3.8.11",
-    "typescript": "~1.5.3",
-    "gulp-typescript": "~2.8.0"
-  }
-}
+{
+  "name": "BabylonJSActionsBuilder",
+  "version": "2.2.0",
+  "description": "",
+  "main": "",
+  "devDependencies": {
+    "gulp": "^3.8.11",
+    "gulp-typescript": "^3.1.4"
+  }
+}

+ 69 - 69
Exporters/3ds Max/ActionsBuilder/raphaeljs.d.ts

@@ -1,69 +1,69 @@
-/*
-Raphael.js declarations
-*/
-
-// Raphael.js bounding box interface
-interface RaphaelBoundingBox {
-    width: number;
-    height: number;
-}
-
-// Raphael.js animation interface
-interface RaphaelAnimation
-{ }
-
-// Raphael.js element interface
-interface RaphaelElement {
-    attr(attribute: string, value?: any): any;
-
-    remove(): void;
-
-    hide(): void;
-    show(): void;
-
-    isPointInside(x: number, y: number): boolean;
-    getBBox(): RaphaelBoundingBox;
-
-    animate(attributes: any, time: number, type: string, callback?: () => void): void;
-    stop(animation: RaphaelAnimation);
-    animation: RaphaelAnimation;
-
-    click(onClick: (event: MouseEvent) => void);
-    drag(onMove: (dx: number, dy: number, x: number, y: number) => void, onStart: (x: number, y: number, event: MouseEvent) => void, onEnd: (event: MouseEvent) => void): void;
-    undrag(): void;
-}
-
-// Raphael.js rect interface
-interface Rect extends RaphaelElement
-{ }
-
-// Raphael.js text interface
-interface Text extends RaphaelElement
-{ }
-
-// Raphael.js path interface
-interface Path extends RaphaelElement
-{ }
-
-// Raphael.js rgb interface
-interface RaphaelColor
-{ }
-
-// Raphael.js paper interface
-interface Paper {
-    canvas: HTMLCanvasElement;
-
-    width: number;
-    height: number;
-    setSize(width: number, height: number);
-
-    rect(x: number, y: number, width: number, height: number, r?: number): Rect;
-    text(x: number, y: number, text: string): Text;
-    path(pathString: string);
-}
-
-// Raphael.js
-declare var Raphael: {
-    (containerID: string, width: number, height: number): Paper;
-    rgb(r: number, g: number, b: number): RaphaelColor;
-}
+/*
+Raphael.js declarations
+*/
+
+// Raphael.js bounding box interface
+interface RaphaelBoundingBox {
+    width: number;
+    height: number;
+}
+
+// Raphael.js animation interface
+interface RaphaelAnimation
+{ }
+
+// Raphael.js element interface
+interface RaphaelElement {
+    attr(attribute: string, value?: any): any;
+
+    remove(): void;
+
+    hide(): void;
+    show(): void;
+
+    isPointInside(x: number, y: number): boolean;
+    getBBox(): RaphaelBoundingBox;
+
+    animate(attributes: any, time: number, type: string, callback?: () => void): void;
+    stop(animation: RaphaelAnimation);
+    animation: RaphaelAnimation;
+
+    click(onClick: (event: MouseEvent) => void);
+    drag(onMove: (dx: number, dy: number, x: number, y: number) => void, onStart: (x: number, y: number, event: MouseEvent) => void, onEnd: (event: MouseEvent) => void): void;
+    undrag(): void;
+}
+
+// Raphael.js rect interface
+interface Rect extends RaphaelElement
+{ }
+
+// Raphael.js text interface
+interface Text extends RaphaelElement
+{ }
+
+// Raphael.js path interface
+interface Path extends RaphaelElement
+{ }
+
+// Raphael.js rgb interface
+interface RaphaelColor
+{ }
+
+// Raphael.js paper interface
+interface Paper {
+    canvas: HTMLCanvasElement;
+
+    width: number;
+    height: number;
+    setSize(width: number, height: number);
+
+    rect(x: number, y: number, width: number, height: number, r?: number): Rect;
+    text(x: number, y: number, text: string): Text;
+    path(pathString: string);
+}
+
+// Raphael.js
+declare var Raphael: {
+    (containerID: string, width: number, height: number): Paper;
+    rgb(r: number, g: number, b: number): RaphaelColor;
+}

+ 31 - 0
Exporters/3ds Max/ActionsBuilder/web.Debug.config

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Pour plus d'informations sur l'utilisation de la transformation web.config, consultez la page http://go.microsoft.com/fwlink/?LinkId=125889 -->
+
+<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
+  <!--
+    Dans l'exemple ci-dessous, la transformation "SetAttributes" changera la valeur de 
+    "connectionString" afin d'utiliser "ReleaseSQLServer" uniquement lorsque le localisateur "Match" 
+    trouve un attribut "name" qui a une valeur "MyDB".
+    
+    <connectionStrings>
+      <add name="MyDB" 
+        connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" 
+        xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
+    </connectionStrings>
+  -->
+  <system.web>
+    <!--
+      
+      Dans l'exemple ci-dessous, la transformation "Replace" remplacera toute la section 
+      <customErrors>  de votre fichier web.config.
+      Dans la mesure où il n'y a qu'une section customErrors sous le 
+      nœud <system.web>, il n'est pas nécessaire d'utiliser l'attribut "xdt:Locator".
+      
+      <customErrors defaultRedirect="GenericError.htm"
+        mode="RemoteOnly" xdt:Transform="Replace">
+        <error statusCode="500" redirect="InternalError.htm"/>
+      </customErrors>
+    -->
+  </system.web>
+</configuration>

+ 32 - 0
Exporters/3ds Max/ActionsBuilder/web.Release.config

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Pour plus d'informations sur l'utilisation de la transformation web.config, consultez la page http://go.microsoft.com/fwlink/?LinkId=125889 -->
+
+<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
+  <!--
+    Dans l'exemple ci-dessous, la transformation "SetAttributes" changera la valeur de 
+    "connectionString" afin d'utiliser "ReleaseSQLServer" uniquement lorsque le localisateur "Match" 
+    trouve un attribut "name" qui a une valeur "MyDB".
+    
+    <connectionStrings>
+      <add name="MyDB" 
+        connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" 
+        xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
+    </connectionStrings>
+  -->
+  <system.web>
+    <compilation xdt:Transform="RemoveAttributes(debug)" />
+    <!--
+      
+      Dans l'exemple ci-dessous, la transformation "Replace" remplacera toute la section 
+      <customErrors>  de votre fichier web.config.
+      Dans la mesure où il n'y a qu'une section customErrors sous le 
+      nœud <system.web>, il n'est pas nécessaire d'utiliser l'attribut "xdt:Locator".
+      
+      <customErrors defaultRedirect="GenericError.htm"
+        mode="RemoteOnly" xdt:Transform="Replace">
+        <error statusCode="500" redirect="InternalError.htm"/>
+      </customErrors>
+    -->
+  </system.web>
+</configuration>

+ 11 - 0
Exporters/3ds Max/ActionsBuilder/web.config

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Pour plus d'informations sur la configuration de votre application ASP.NET, visitez
+  http://go.microsoft.com/fwlink/?LinkId=169433
+  -->
+<configuration>
+  <system.web>
+    <compilation debug="true" targetFramework="4.5" />
+    <httpRuntime targetFramework="4.5" />
+  </system.web>
+</configuration>

+ 3 - 0
Exporters/3ds Max/BabylonExport.Entities/BabylonAbstractMesh.cs

@@ -38,6 +38,9 @@ namespace BabylonExport.Entities
         [DataMember]
         public bool autoAnimateLoop { get; set; }
 
+        [DataMember]
+        public string parentId { get; set; }
+
         public BabylonAbstractMesh()
         {
             position = new[] { 0f, 0f, 0f };

+ 16 - 0
Exporters/3ds Max/BabylonExport.Entities/BabylonDirectionalLight.cs

@@ -0,0 +1,16 @@
+using System.Runtime.Serialization;
+
+namespace BabylonExport.Entities
+{
+    [DataContract]
+    public class BabylonDirectionalLight : BabylonLight
+    {
+        [DataMember]
+        public float shadowOrthoScale { get; set; }
+
+        public BabylonDirectionalLight()
+        {
+            shadowOrthoScale = 0.5f;
+        }
+    }
+}

+ 17 - 0
Exporters/3ds Max/BabylonExport.Entities/BabylonExport.Entities.csproj

@@ -17,6 +17,8 @@
     <SccProvider>SAK</SccProvider>
     <TargetFrameworkProfile>
     </TargetFrameworkProfile>
+    <NuGetPackageImportStamp>
+    </NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -38,9 +40,14 @@
     <Prefer32Bit>false</Prefer32Bit>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="SharpDX">
+      <HintPath>$(SharpDXPackageBinDir)\SharpDX.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
     <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="System.Data" />
@@ -74,7 +81,17 @@
     <Compile Include="BabylonVector3.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\packages\SharpDX.2.6.3\build\SharpDX.targets" Condition="Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SharpDX.2.6.3\build\SharpDX.targets'))" />
+  </Target>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">

+ 0 - 3
Exporters/3ds Max/BabylonExport.Entities/BabylonMesh.cs

@@ -9,9 +9,6 @@ namespace BabylonExport.Entities
         public string id { get; set; }
 
         [DataMember]
-        public string parentId { get; set; }
-
-        [DataMember]
         public string materialId { get; set; }
 
         [DataMember]

+ 9 - 0
Exporters/3ds Max/BabylonExport.Entities/BabylonPBRMaterial.cs

@@ -152,6 +152,9 @@ namespace BabylonExport.Entities
         public bool useRadianceOverAlpha { get; set; }
 
         [DataMember]
+        public bool usePhysicalLightFalloff { get; set; }
+
+        [DataMember]
         public float indexOfRefraction { get; set; }
 
         [DataMember]
@@ -179,6 +182,7 @@ namespace BabylonExport.Entities
             indexOfRefraction = 0.66f;
             useRadianceOverAlpha = true;
             useSpecularOverAlpha = true;
+            usePhysicalLightFalloff = true;
             useEmissiveAsIllumination = false;
 
             // Default Null Metallic Workflow
@@ -205,5 +209,10 @@ namespace BabylonExport.Entities
             overloadedEmissive = new[] {1f, 1f, 1f };
             overloadedReflection = new[] { 1f, 1f, 1f };
         }
+
+        public void SetCustomType(string type)
+        {
+            this.customType = type;
+        }
     }
 }

+ 11 - 0
Exporters/3ds Max/BabylonExport.Entities/BabylonShadowGenerator.cs

@@ -24,6 +24,9 @@ namespace BabylonExport.Entities
         public bool useBlurVarianceShadowMap { get; set; }
 
         [DataMember]
+        public float darkness { get; set; }
+
+        [DataMember]
         public float blurScale { get; set; }
 
         [DataMember]
@@ -35,5 +38,13 @@ namespace BabylonExport.Entities
         [DataMember]
         public bool forceBackFacesOnly { get; set; }
 
+        public BabylonShadowGenerator()
+        {
+            darkness = 0;
+            blurScale = 2;
+            blurBoxOffset = 0;
+            bias = 0.00005f;
+            forceBackFacesOnly = false;
+        }
     }
 }

+ 3 - 3
Exporters/3ds Max/BabylonExport.Entities/packages.config

@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
-  <package id="SharpDX" version="2.6.3" targetFramework="net40" />
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="SharpDX" version="2.6.3" targetFramework="net35" />
 </packages>

+ 66 - 0
Exporters/3ds Max/BabylonFileConverter/BabylonFileConverter.csproj

@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{A6B76356-1D1C-4C82-8199-A6406DA85A95}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>BabylonFileConverter</RootNamespace>
+    <AssemblyName>BabylonFileConverter</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+    <RestorePackages>true</RestorePackages>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="BinaryConverter.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 374 - 0
Exporters/3ds Max/BabylonFileConverter/BinaryConverter.cs

@@ -0,0 +1,374 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BabylonFileConverter
+{
+    public static class BinaryConverter
+    {
+        public enum DataType { Int32, Float };
+
+        public static void Convert(string srcFilename, string dstPath, Action<string> onMessage, Action<string> onError)
+        {
+            try
+            {
+                if (!Directory.Exists(dstPath))
+                    Directory.CreateDirectory(dstPath);
+
+                string srcPath = Path.GetDirectoryName(srcFilename);
+                string dstFilename = Path.Combine(dstPath, Path.GetFileNameWithoutExtension(srcFilename) + ".binary.babylon");
+
+                dynamic scene;
+
+                // Loading
+                onMessage("Loading " + srcFilename);
+
+                using (var streamReader = new StreamReader(srcFilename))
+                {
+                    using (var reader = new JsonTextReader(streamReader))
+                    {
+                        scene = JObject.Load(reader);
+                    }
+                }
+
+                // Marking scene
+                string objName = scene.name;
+
+                if (string.IsNullOrEmpty(objName))
+                    objName = Path.GetFileNameWithoutExtension(srcFilename);
+
+                var atDot = objName.IndexOf(".incremental");
+                if (atDot > 0)
+                    objName = objName.Substring(0, atDot);
+
+                scene["autoClear"] = true;
+                scene["useDelayedTextureLoading"] = true;
+
+                var doNotDelayLoadingForGeometries = new List<string>();
+
+                // Parsing meshes
+                var meshes = (JArray)scene.meshes;
+                foreach (dynamic mesh in meshes)
+                {
+                    if (mesh.checkCollisions.Value) // Do not delay load collisions object
+                    {
+                        if (mesh.geometryId != null)
+                            doNotDelayLoadingForGeometries.Add(mesh.geometryId.Value);
+                        continue;
+                    }
+
+                    Extract(srcPath, dstPath, objName, mesh, true);
+                }
+
+
+                // Parsing vertexData
+                var geometries = scene.geometries;
+                if (geometries != null)
+                {
+                    var vertexData = (JArray)geometries.vertexData;
+                    foreach (dynamic geometry in vertexData)
+                    {
+                        var id = geometry.id.Value;
+
+                        if (doNotDelayLoadingForGeometries.Any(g => g == id))
+                            continue;
+
+                        Extract(srcPath, dstPath, objName, geometry, false);
+                    }
+                }
+
+                // Saving                
+                onMessage("Saving " + dstFilename);
+                string json = scene.ToString(Formatting.Indented);
+
+                using (var writer = new StreamWriter(WebUtility.UrlDecode(dstFilename)))
+                {
+                    writer.Write(json);
+                }
+            }
+            catch (Exception ex)
+            {
+                onError(ex.Message);
+            }
+        }
+
+
+        static void Extract(string srcPath, string dstPath, string objName, dynamic meshObj, bool isMesh)
+        {
+            string dstFilename = meshObj.delayLoadingFile;
+            string dstExt = (isMesh ? ".babylonbinarymeshdata" : ".babylonbinarygeometrydata");
+
+            if (!string.IsNullOrEmpty(dstFilename))
+            {
+                string filename = WebUtility.UrlDecode(Path.Combine(srcPath, (string)meshObj.delayLoadingFile));
+
+                using (var streamReader = new StreamReader(filename))
+                {
+                    using (var reader = new JsonTextReader(streamReader))
+                    {
+                        var meshData = JObject.Load(reader);
+                        meshObj.positions = meshData["positions"];
+                        meshObj.normals = meshData["normals"];
+                        meshObj.indices = meshData["indices"];
+                        meshObj.uvs = meshData["uvs"];
+                        meshObj.uvs2 = meshData["uvs2"];
+                        meshObj.colors = meshData["colors"];
+                        meshObj.matricesIndices = meshData["matricesIndices"];
+                        meshObj.matricesWeights = meshData["matricesWeights"];
+                        meshObj.subMeshes = meshData["subMeshes"];
+                    }
+                }
+            }
+
+            if (meshObj.positions == null || meshObj.positions.Count == 0 
+                || meshObj.normals == null || meshObj.normals.Count == 0
+                || meshObj.indices == null || meshObj.indices.Count == 0)
+                return;
+
+            ComputeBoundingBox(meshObj);
+
+            string meshName = meshObj.name.ToString();
+            meshName = meshName.Trim();
+            if (meshName.Length > 40)
+                meshName = meshName.Substring(0, 40);
+
+            if (isMesh && !string.IsNullOrEmpty(meshName))
+                dstFilename = objName + "." + meshName + "." + meshObj.id.ToString() + dstExt;
+            else
+                dstFilename = objName + meshObj.id.ToString() + dstExt;
+
+            dstFilename = dstFilename.Replace("+", "_").Replace(" ", "_").Replace("/", "_").Replace("\\", "_").Replace(":", "_");
+
+            meshObj.delayLoadingFile = WebUtility.UrlEncode(dstFilename);
+
+            var binaryInfo = new JObject();
+
+            using (var stream = File.Open(WebUtility.UrlDecode(Path.Combine(dstPath, dstFilename)), FileMode.Create))
+            {
+                var writer = new BinaryWriter(stream);
+
+                if (meshObj.positions != null && meshObj.positions.Count > 0)
+                {
+                    var attrData = new JObject();
+                    attrData["count"] = meshObj.positions.Count;
+                    attrData["stride"] = 3;
+                    attrData["offset"] = stream.Length;
+                    attrData["dataType"] = (int)DataType.Float;
+
+                    binaryInfo["positionsAttrDesc"] = attrData;
+
+                    for (int x = 0; x < meshObj.positions.Count; x++)
+                        writer.Write((float)meshObj.positions[x]);
+
+                    meshObj.positions = null;
+                }
+
+
+                if (meshObj.colors != null && meshObj.colors.Count > 0)
+                {
+                    var attrData = new JObject();
+                    attrData["count"] = meshObj.colors.Count;
+                    attrData["stride"] = 3;
+                    attrData["offset"] = stream.Length;
+                    attrData["dataType"] = (int)DataType.Float;
+
+                    binaryInfo["colorsAttrDesc"] = attrData;
+
+                    for (int x = 0; x < meshObj.colors.Count; x++)
+                        writer.Write((float)meshObj.colors[x]);
+
+                    meshObj["hasColors"] = true;
+                    meshObj.colors = null;
+                }
+
+
+                if (meshObj.normals != null && meshObj.normals.Count > 0)
+                {
+                    var attrData = new JObject();
+                    attrData["count"] = meshObj.normals.Count;
+                    attrData["stride"] = 3;
+                    attrData["offset"] = stream.Length;
+                    attrData["dataType"] = (int)DataType.Float;
+
+                    binaryInfo["normalsAttrDesc"] = attrData;
+
+                    for (int x = 0; x < meshObj.normals.Count; x++)
+                        writer.Write((float)meshObj.normals[x]);
+
+                    meshObj.normals = null;
+                }
+
+
+                if (meshObj.uvs != null && meshObj.uvs.Count > 0)
+                {
+                    var attrData = new JObject();
+                    attrData["count"] = meshObj.uvs.Count;
+                    attrData["stride"] = 2;
+                    attrData["offset"] = stream.Length;
+                    attrData["dataType"] = (int)DataType.Float;
+
+                    binaryInfo["uvsAttrDesc"] = attrData;
+
+                    for (int x = 0; x < meshObj.uvs.Count; x++)
+                        writer.Write((float)meshObj.uvs[x]);
+
+                    meshObj["hasUVs"] = true;
+                    meshObj.uvs = null;
+                }
+
+
+                if (meshObj.uvs2 != null && meshObj.uvs2.Count > 0)
+                {
+                    var attrData = new JObject();
+                    attrData["count"] = meshObj.uvs2.Count;
+                    attrData["stride"] = 2;
+                    attrData["offset"] = stream.Length;
+                    attrData["dataType"] = (int)DataType.Float;
+
+                    binaryInfo["uvs2AttrDesc"] = attrData;
+
+                    for (int x = 0; x < meshObj.uvs2.Count; x++)
+                        writer.Write((float)meshObj.uvs2[x]);
+
+                    meshObj["hasUVs2"] = true;
+                    meshObj.uvs2 = null;
+                }
+
+
+                if (meshObj.indices != null && meshObj.indices.Count > 0)
+                {
+                    var attrData = new JObject();
+                    attrData["count"] = meshObj.indices.Count;
+                    attrData["stride"] = 1;
+                    attrData["offset"] = stream.Length;
+                    attrData["dataType"] = (int)DataType.Int32;
+
+                    binaryInfo["indicesAttrDesc"] = attrData;
+
+                    for (int x = 0; x < meshObj.indices.Count; x++)
+                        writer.Write((int)meshObj.indices[x]);
+
+                    meshObj.indices = null;
+                }
+
+
+                if (meshObj.matricesIndices != null && meshObj.matricesIndices.Count > 0)
+                {
+                    var attrData = new JObject();
+                    attrData["count"] = meshObj.matricesIndices.Count;
+                    attrData["stride"] = 1;
+                    attrData["offset"] = stream.Length;
+                    attrData["dataType"] = (int)DataType.Int32;
+
+                    binaryInfo["matricesIndicesAttrDesc"] = attrData;
+
+                    for (int x = 0; x < meshObj.matricesIndices.Count; x++)
+                        writer.Write((int)meshObj.matricesIndices[x]);
+
+                    meshObj["hasMatricesIndices"] = true;
+                    meshObj.matricesIndices = null;
+                }
+
+
+                if (meshObj.matricesWeights != null && meshObj.matricesWeights.Count > 0)
+                {
+                    var attrData = new JObject();
+                    attrData["count"] = meshObj.matricesWeights.Count;
+                    attrData["stride"] = 2;
+                    attrData["offset"] = stream.Length;
+                    attrData["dataType"] = (int)DataType.Float;
+
+                    binaryInfo["matricesWeightsAttrDesc"] = attrData;
+
+                    for (int x = 0; x < meshObj.matricesWeights.Count; x++)
+                        writer.Write((float)meshObj.matricesWeights[x]);
+
+                    meshObj["hasMatricesWeights"] = true;
+                    meshObj.matricesWeights = null;
+                }
+
+
+                if (isMesh && meshObj.subMeshes != null && meshObj.subMeshes.Count > 0)
+                {
+                    var attrData = new JObject();
+                    attrData["count"] = meshObj.subMeshes.Count;
+                    attrData["stride"] = 5;
+                    attrData["offset"] = stream.Length;
+                    attrData["dataType"] = (int)DataType.Int32;
+
+                    binaryInfo["subMeshesAttrDesc"] = attrData;
+
+                    var smData = new int[5];
+
+                    for (int x = 0; x < meshObj.subMeshes.Count; x++)
+                    {
+                        smData[0] = meshObj.subMeshes[x].materialIndex;
+                        smData[1] = meshObj.subMeshes[x].verticesStart;
+                        smData[2] = meshObj.subMeshes[x].verticesCount;
+                        smData[3] = meshObj.subMeshes[x].indexStart;
+                        smData[4] = meshObj.subMeshes[x].indexCount;
+
+                        for (int y = 0; y < smData.Length; y++)
+                            writer.Write(smData[y]);
+                    }
+
+                    meshObj.subMeshes = null;
+                }
+            }
+
+            meshObj["_binaryInfo"] = binaryInfo;
+        }
+
+
+        static void ComputeBoundingBox(dynamic meshOrGeometry)
+        {
+            // Compute bounding boxes
+            var positions = ((JArray)meshOrGeometry.positions).Select(v => v.Value<float>()).ToArray();
+            var minimum = new[] { float.MaxValue, float.MaxValue, float.MaxValue };
+            var maximum = new[] { float.MinValue, float.MinValue, float.MinValue };
+
+            for (var index = 0; index < positions.Length; index += 3)
+            {
+                var x = positions[index];
+                var y = positions[index + 1];
+                var z = positions[index + 2];
+
+                if (x < minimum[0])
+                {
+                    minimum[0] = x;
+                }
+                if (x > maximum[0])
+                {
+                    maximum[0] = x;
+                }
+
+                if (y < minimum[1])
+                {
+                    minimum[1] = y;
+                }
+                if (y > maximum[1])
+                {
+                    maximum[1] = y;
+                }
+
+                if (z < minimum[2])
+                {
+                    minimum[2] = z;
+                }
+                if (z > maximum[2])
+                {
+                    maximum[2] = z;
+                }
+            }
+
+            meshOrGeometry["boundingBoxMinimum"] = new JArray(minimum);
+            meshOrGeometry["boundingBoxMaximum"] = new JArray(maximum);
+        }
+    }
+}

+ 36 - 0
Exporters/3ds Max/BabylonFileConverter/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("BabylonFileConverter")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("BabylonFileConverter")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f54d9455-96c3-4e01-bb67-9213d8975373")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 4 - 0
Exporters/3ds Max/BabylonFileConverter/packages.config

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
+</packages>

二進制
Exporters/3ds Max/Max2Babylon-0.5.0.zip


+ 223 - 34
Exporters/3ds Max/Max2Babylon.sln

@@ -1,34 +1,223 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.30501.0
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Max2Babylon", "Max2Babylon\Max2Babylon.csproj", "{DD7C931A-8FAF-4318-BB74-71DC858CC489}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BabylonExport.Entities", "BabylonExport.Entities\BabylonExport.Entities.csproj", "{6150965A-658C-4263-89AD-4F980EB0675D}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Max2Babylon2015", "Max2Babylon\2015\Max2Babylon2015.csproj", "{DD7C931A-8FAF-4318-BB74-71DC858CC400}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Any CPU = Debug|Any CPU
-		Release|Any CPU = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Release|Any CPU.Build.0 = Release|Any CPU
-		{6150965A-658C-4263-89AD-4F980EB0675D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{6150965A-658C-4263-89AD-4F980EB0675D}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{6150965A-658C-4263-89AD-4F980EB0675D}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{6150965A-658C-4263-89AD-4F980EB0675D}.Release|Any CPU.Build.0 = Release|Any CPU
-		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Release|Any CPU.Build.0 = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3ds Max", "3ds Max", "{2139CC27-1C89-49C8-95AC-7715ACBADC1F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BabylonExport.Entities", "BabylonExport.Entities\BabylonExport.Entities.csproj", "{6150965A-658C-4263-89AD-4F980EB0675D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Max2Babylon", "Max2Babylon\Max2Babylon.csproj", "{DD7C931A-8FAF-4318-BB74-71DC858CC489}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Max2Babylon2015", "Max2Babylon\2015\Max2Babylon2015.csproj", "{DD7C931A-8FAF-4318-BB74-71DC858CC400}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BabylonFileConverter", "BabylonFileConverter\BabylonFileConverter.csproj", "{A6B76356-1D1C-4C82-8199-A6406DA85A95}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ActionsBuilder", "ActionsBuilder\ActionsBuilder.csproj", "{293A754C-3D80-42FB-99D8-7C9386CD297E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Max2Babylon2017", "Max2Babylon\2017\Max2Babylon2017.csproj", "{2F49C726-A1F8-40D4-859F-1355949608DC}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|ARM = Debug|ARM
+		Debug|Mixed Platforms = Debug|Mixed Platforms
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Profile|Any CPU = Profile|Any CPU
+		Profile|ARM = Profile|ARM
+		Profile|Mixed Platforms = Profile|Mixed Platforms
+		Profile|Win32 = Profile|Win32
+		Profile|x64 = Profile|x64
+		Profile|x86 = Profile|x86
+		Release|Any CPU = Release|Any CPU
+		Release|ARM = Release|ARM
+		Release|Mixed Platforms = Release|Mixed Platforms
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Debug|x64.Build.0 = Debug|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Profile|Any CPU.ActiveCfg = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Profile|Any CPU.Build.0 = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Profile|ARM.ActiveCfg = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Profile|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Profile|Mixed Platforms.Build.0 = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Profile|Win32.ActiveCfg = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Profile|x64.ActiveCfg = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Profile|x86.ActiveCfg = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Release|Any CPU.Build.0 = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Release|ARM.ActiveCfg = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Release|Win32.ActiveCfg = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Release|x64.ActiveCfg = Release|Any CPU
+		{6150965A-658C-4263-89AD-4F980EB0675D}.Release|x86.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Debug|x64.Build.0 = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Profile|Any CPU.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Profile|Any CPU.Build.0 = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Profile|ARM.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Profile|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Profile|Mixed Platforms.Build.0 = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Profile|Win32.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Profile|x64.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Profile|x86.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Release|Any CPU.Build.0 = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Release|ARM.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Release|Win32.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Release|x64.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489}.Release|x86.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Debug|x64.Build.0 = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Profile|Any CPU.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Profile|Any CPU.Build.0 = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Profile|ARM.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Profile|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Profile|Mixed Platforms.Build.0 = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Profile|Win32.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Profile|x64.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Profile|x86.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Release|Any CPU.Build.0 = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Release|ARM.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Release|Win32.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Release|x64.ActiveCfg = Release|Any CPU
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400}.Release|x86.ActiveCfg = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Debug|ARM.Build.0 = Debug|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Debug|Win32.Build.0 = Debug|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Debug|x64.Build.0 = Debug|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Debug|x86.Build.0 = Debug|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Profile|Any CPU.ActiveCfg = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Profile|Any CPU.Build.0 = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Profile|ARM.ActiveCfg = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Profile|ARM.Build.0 = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Profile|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Profile|Mixed Platforms.Build.0 = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Profile|Win32.ActiveCfg = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Profile|Win32.Build.0 = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Profile|x64.ActiveCfg = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Profile|x64.Build.0 = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Profile|x86.ActiveCfg = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Profile|x86.Build.0 = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Release|ARM.ActiveCfg = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Release|ARM.Build.0 = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Release|Win32.ActiveCfg = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Release|Win32.Build.0 = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Release|x64.ActiveCfg = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Release|x64.Build.0 = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Release|x86.ActiveCfg = Release|Any CPU
+		{A6B76356-1D1C-4C82-8199-A6406DA85A95}.Release|x86.Build.0 = Release|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Debug|x64.Build.0 = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Profile|Any CPU.ActiveCfg = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Profile|Any CPU.Build.0 = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Profile|ARM.ActiveCfg = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Profile|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Profile|Mixed Platforms.Build.0 = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Profile|Win32.ActiveCfg = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Profile|x64.ActiveCfg = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Profile|x86.ActiveCfg = Debug|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Release|ARM.ActiveCfg = Release|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Release|Win32.ActiveCfg = Release|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Release|x64.ActiveCfg = Release|Any CPU
+		{293A754C-3D80-42FB-99D8-7C9386CD297E}.Release|x86.ActiveCfg = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Debug|ARM.Build.0 = Debug|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Debug|Win32.Build.0 = Debug|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Debug|x64.Build.0 = Debug|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Debug|x86.Build.0 = Debug|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Profile|Any CPU.ActiveCfg = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Profile|Any CPU.Build.0 = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Profile|ARM.ActiveCfg = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Profile|ARM.Build.0 = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Profile|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Profile|Mixed Platforms.Build.0 = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Profile|Win32.ActiveCfg = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Profile|Win32.Build.0 = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Profile|x64.ActiveCfg = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Profile|x64.Build.0 = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Profile|x86.ActiveCfg = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Profile|x86.Build.0 = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Release|ARM.ActiveCfg = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Release|ARM.Build.0 = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Release|Win32.ActiveCfg = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Release|Win32.Build.0 = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Release|x64.ActiveCfg = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Release|x64.Build.0 = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Release|x86.ActiveCfg = Release|Any CPU
+		{2F49C726-A1F8-40D4-859F-1355949608DC}.Release|x86.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{DD7C931A-8FAF-4318-BB74-71DC858CC489} = {2139CC27-1C89-49C8-95AC-7715ACBADC1F}
+		{DD7C931A-8FAF-4318-BB74-71DC858CC400} = {2139CC27-1C89-49C8-95AC-7715ACBADC1F}
+		{2F49C726-A1F8-40D4-859F-1355949608DC} = {2139CC27-1C89-49C8-95AC-7715ACBADC1F}
+	EndGlobalSection
+EndGlobal

+ 273 - 293
Exporters/3ds Max/Max2Babylon/2015/Max2Babylon2015.csproj

@@ -1,294 +1,274 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{DD7C931A-8FAF-4318-BB74-71DC858CC400}</ProjectGuid>
-    <OutputType>Library</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>Max2Babylon</RootNamespace>
-    <AssemblyName>Max2Babylon</AssemblyName>
-    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <TargetFrameworkProfile />
-    <SccProjectName>SAK</SccProjectName>
-    <SccLocalPath>SAK</SccLocalPath>
-    <SccAuxPath>SAK</SccAuxPath>
-    <SccProvider>SAK</SccProvider>
-    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
-    <RestorePackages>true</RestorePackages>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>C:\Program Files\Autodesk\3ds Max 2015\bin\assemblies\</OutputPath>
-    <DefineConstants>TRACE;DEBUG;MAX2015</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <Prefer32Bit>false</Prefer32Bit>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>C:\Program Files\Autodesk\3ds Max 2013\bin\assemblies\</OutputPath>
-    <DefineConstants>TRACE;MAX2015</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="Autodesk.Max, Version=17.0.630.0, Culture=neutral, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\..\..\..\..\Repos\Babylon.js\Exporters\3ds Max\Max2Babylon\2015\Refs\Autodesk.Max.dll</HintPath>
-    </Reference>
-    <Reference Include="BabylonFileConverter, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\Refs\BabylonFileConverter.dll</HintPath>
-    </Reference>
-    <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\..\packages\Newtonsoft.Json.6.0.7\lib\net45\Newtonsoft.Json.dll</HintPath>
-    </Reference>
-    <Reference Include="SharpDX, Version=2.4.2.0, Culture=neutral, PublicKeyToken=627a3d6d1956f55a, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\..\BabylonExport.Core\Refs\SharpDX.dll</HintPath>
-    </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Drawing" />
-    <Reference Include="System.Runtime.Serialization" />
-    <Reference Include="System.Web" />
-    <Reference Include="System.Windows.Forms" />
-    <Reference Include="System.Data.DataSetExtensions" />
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="..\BabylonActionCallback.cs">
-      <Link>BabylonActionCallback.cs</Link>
-    </Compile>
-    <Compile Include="..\BabylonExportActionItem.cs">
-      <Link>BabylonExportActionItem.cs</Link>
-    </Compile>
-    <Compile Include="..\BabylonPropertiesActionItem.cs">
-      <Link>BabylonPropertiesActionItem.cs</Link>
-    </Compile>
-    <Compile Include="..\Descriptor.cs">
-      <Link>Descriptor.cs</Link>
-    </Compile>
-    <Compile Include="..\Exporter\ActionBuilder\BabylonActionsBuilderActionItem.cs">
-      <Link>Exporter\ActionBuilder\BabylonActionsBuilderActionItem.cs</Link>
-    </Compile>
-    <Compile Include="..\Exporter\ActionBuilder\BabylonExporter.Action.cs">
-      <Link>Exporter\ActionBuilder\BabylonExporter.Action.cs</Link>
-    </Compile>
-    <Compile Include="..\Exporter\BabylonExporter.Animation.cs">
-      <Link>Exporter\BabylonExporter.Animation.cs</Link>
-    </Compile>
-    <Compile Include="..\Exporter\BabylonExporter.Camera.cs">
-      <Link>Exporter\BabylonExporter.Camera.cs</Link>
-    </Compile>
-    <Compile Include="..\Exporter\BabylonExporter.cs">
-      <Link>Exporter\BabylonExporter.cs</Link>
-    </Compile>
-    <Compile Include="..\Exporter\BabylonExporter.Light.cs">
-      <Link>Exporter\BabylonExporter.Light.cs</Link>
-    </Compile>
-    <Compile Include="..\Exporter\BabylonExporter.Material.cs">
-      <Link>Exporter\BabylonExporter.Material.cs</Link>
-    </Compile>
-    <Compile Include="..\Exporter\BabylonExporter.Mesh.cs">
-      <Link>Exporter\BabylonExporter.Mesh.cs</Link>
-    </Compile>
-    <Compile Include="..\Exporter\BabylonExporter.ShadowGenerator.cs">
-      <Link>Exporter\BabylonExporter.ShadowGenerator.cs</Link>
-    </Compile>
-    <Compile Include="..\Exporter\BabylonExporter.Skeleton.cs">
-      <Link>Exporter\BabylonExporter.Skeleton.cs</Link>
-    </Compile>
-    <Compile Include="..\Exporter\BabylonExporter.Texture.cs">
-      <Link>Exporter\BabylonExporter.Texture.cs</Link>
-    </Compile>
-    <Compile Include="..\Exporter\GlobalVertex.cs">
-      <Link>Exporter\GlobalVertex.cs</Link>
-    </Compile>
-    <Compile Include="..\Forms\ActionsBuilderForm.cs">
-      <Link>Forms\ActionsBuilderForm.cs</Link>
-      <SubType>Form</SubType>
-    </Compile>
-    <Compile Include="..\Forms\ActionsBuilderForm.designer.cs">
-      <Link>Forms\ActionsBuilderForm.designer.cs</Link>
-      <DependentUpon>ActionsBuilderForm.cs</DependentUpon>
-    </Compile>
-    <Compile Include="..\Forms\CameraPropertiesForm.cs">
-      <Link>Forms\CameraPropertiesForm.cs</Link>
-      <SubType>Form</SubType>
-    </Compile>
-    <Compile Include="..\Forms\CameraPropertiesForm.Designer.cs">
-      <Link>Forms\CameraPropertiesForm.Designer.cs</Link>
-      <DependentUpon>CameraPropertiesForm.cs</DependentUpon>
-    </Compile>
-    <Compile Include="..\Forms\ExporterForm.cs">
-      <Link>Forms\ExporterForm.cs</Link>
-      <SubType>Form</SubType>
-    </Compile>
-    <Compile Include="..\Forms\ExporterForm.Designer.cs">
-      <Link>Forms\ExporterForm.Designer.cs</Link>
-      <DependentUpon>ExporterForm.cs</DependentUpon>
-    </Compile>
-    <Compile Include="..\Forms\LightPropertiesForm.cs">
-      <Link>Forms\LightPropertiesForm.cs</Link>
-      <SubType>Form</SubType>
-    </Compile>
-    <Compile Include="..\Forms\LightPropertiesForm.Designer.cs">
-      <Link>Forms\LightPropertiesForm.Designer.cs</Link>
-      <DependentUpon>LightPropertiesForm.cs</DependentUpon>
-    </Compile>
-    <Compile Include="..\Forms\ObjectPropertiesForm.cs">
-      <Link>Forms\ObjectPropertiesForm.cs</Link>
-      <SubType>Form</SubType>
-    </Compile>
-    <Compile Include="..\Forms\ObjectPropertiesForm.Designer.cs">
-      <Link>Forms\ObjectPropertiesForm.Designer.cs</Link>
-      <DependentUpon>ObjectPropertiesForm.cs</DependentUpon>
-    </Compile>
-    <Compile Include="..\Forms\ScenePropertiesForm.cs">
-      <Link>Forms\ScenePropertiesForm.cs</Link>
-      <SubType>Form</SubType>
-    </Compile>
-    <Compile Include="..\Forms\ScenePropertiesForm.Designer.cs">
-      <Link>Forms\ScenePropertiesForm.Designer.cs</Link>
-      <DependentUpon>ScenePropertiesForm.cs</DependentUpon>
-    </Compile>
-    <Compile Include="..\Forms\Vector3Control.cs">
-      <Link>Forms\Vector3Control.cs</Link>
-      <SubType>UserControl</SubType>
-    </Compile>
-    <Compile Include="..\Forms\Vector3Control.Designer.cs">
-      <Link>Forms\Vector3Control.Designer.cs</Link>
-      <DependentUpon>Vector3Control.cs</DependentUpon>
-    </Compile>
-    <Compile Include="..\GlobalUtility.cs">
-      <Link>GlobalUtility.cs</Link>
-    </Compile>
-    <Compile Include="..\JsonTextWriterOptimized.cs">
-      <Link>JsonTextWriterOptimized.cs</Link>
-    </Compile>
-    <Compile Include="..\Loader.cs">
-      <Link>Loader.cs</Link>
-    </Compile>
-    <Compile Include="..\Tools\Tools.cs">
-      <Link>Tools\Tools.cs</Link>
-    </Compile>
-    <Compile Include="..\Tools\VNormal.cs">
-      <Link>Tools\VNormal.cs</Link>
-    </Compile>
-    <Compile Include="..\Tools\WebServer.cs">
-      <Link>Tools\WebServer.cs</Link>
-    </Compile>
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Properties\Resources.Designer.cs">
-      <AutoGen>True</AutoGen>
-      <DesignTime>True</DesignTime>
-      <DependentUpon>Resources.resx</DependentUpon>
-    </Compile>
-  </ItemGroup>
-  <ItemGroup>
-    <Content Include="..\Exporter\ActionBuilder\ActionsBuilder\action.js">
-      <Link>Exporter\ActionBuilder\ActionsBuilder\action.js</Link>
-    </Content>
-    <Content Include="..\Exporter\ActionBuilder\ActionsBuilder\actionkinds.js">
-      <Link>Exporter\ActionBuilder\ActionsBuilder\actionkinds.js</Link>
-    </Content>
-    <Content Include="..\Exporter\ActionBuilder\ActionsBuilder\contextmenu.js">
-      <Link>Exporter\ActionBuilder\ActionsBuilder\contextmenu.js</Link>
-    </Content>
-    <Content Include="..\Exporter\ActionBuilder\ActionsBuilder\fonts.css">
-      <Link>Exporter\ActionBuilder\ActionsBuilder\fonts.css</Link>
-    </Content>
-    <Content Include="..\Exporter\ActionBuilder\ActionsBuilder\index.css">
-      <Link>Exporter\ActionBuilder\ActionsBuilder\index.css</Link>
-    </Content>
-    <Content Include="..\Exporter\ActionBuilder\ActionsBuilder\index.html">
-      <Link>Exporter\ActionBuilder\ActionsBuilder\index.html</Link>
-    </Content>
-    <Content Include="..\Exporter\ActionBuilder\ActionsBuilder\list.js">
-      <Link>Exporter\ActionBuilder\ActionsBuilder\list.js</Link>
-    </Content>
-    <Content Include="..\Exporter\ActionBuilder\ActionsBuilder\parametersManager.js">
-      <Link>Exporter\ActionBuilder\ActionsBuilder\parametersManager.js</Link>
-    </Content>
-    <Content Include="..\Exporter\ActionBuilder\ActionsBuilder\raphael.js">
-      <Link>Exporter\ActionBuilder\ActionsBuilder\raphael.js</Link>
-    </Content>
-    <Content Include="..\Exporter\ActionBuilder\ActionsBuilder\utils.js">
-      <Link>Exporter\ActionBuilder\ActionsBuilder\utils.js</Link>
-    </Content>
-    <Content Include="..\Exporter\ActionBuilder\ActionsBuilder\viewer.js">
-      <Link>Exporter\ActionBuilder\ActionsBuilder\viewer.js</Link>
-    </Content>
-    <Content Include="..\Exporter\ActionBuilder\ActionsBuilder\viewsertoolbar.js">
-      <Link>Exporter\ActionBuilder\ActionsBuilder\viewsertoolbar.js</Link>
-    </Content>
-    <Content Include="Refs\Autodesk.Max.dll" />
-  </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Include="..\Forms\ActionsBuilderForm.resx">
-      <Link>Forms\ActionsBuilderForm.resx</Link>
-      <DependentUpon>ActionsBuilderForm.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="..\Forms\CameraPropertiesForm.resx">
-      <Link>Forms\CameraPropertiesForm.resx</Link>
-      <DependentUpon>CameraPropertiesForm.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="..\Forms\ExporterForm.resx">
-      <Link>Forms\ExporterForm.resx</Link>
-      <DependentUpon>ExporterForm.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="..\Forms\LightPropertiesForm.resx">
-      <Link>Forms\LightPropertiesForm.resx</Link>
-      <DependentUpon>LightPropertiesForm.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="..\Forms\ObjectPropertiesForm.resx">
-      <Link>Forms\ObjectPropertiesForm.resx</Link>
-      <DependentUpon>ObjectPropertiesForm.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="..\Forms\ScenePropertiesForm.resx">
-      <Link>Forms\ScenePropertiesForm.resx</Link>
-      <DependentUpon>ScenePropertiesForm.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="..\Forms\Vector3Control.resx">
-      <Link>Forms\Vector3Control.resx</Link>
-      <DependentUpon>Vector3Control.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="Properties\Resources.resx">
-      <Generator>ResXFileCodeGenerator</Generator>
-      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\..\BabylonExport.Entities\BabylonExport.Entities.csproj">
-      <Project>{6150965a-658c-4263-89ad-4f980eb0675d}</Project>
-      <Name>BabylonExport.Entities</Name>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <PropertyGroup>
-    <PostBuildEvent>mkdir "$(OutDir)BabylonActionsBuilder"
-mkdir "$(OutDir)BabylonActionsBuilder\fonts\SinkinSans"
-copy "$(SolutionDir)Max2Babylon\Exporter\ActionBuilder\ActionsBuilder\" "$(OutDir)BabylonActionsBuilder\"
-copy "$(SolutionDir)Max2Babylon\Exporter\ActionBuilder\ActionsBuilder\fonts\SinkinSans" "$(OutDir)BabylonActionsBuilder\fonts\SinkinSans"
-copy "$(SolutionDir)babylon.max.js" "$(OutDir)BabylonActionsBuilder\babylon.max.js"</PostBuildEvent>
-  </PropertyGroup>
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
-  -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{DD7C931A-8FAF-4318-BB74-71DC858CC400}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Max2Babylon</RootNamespace>
+    <AssemblyName>Max2Babylon</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+    <RestorePackages>true</RestorePackages>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>C:\Program Files\Autodesk\3ds Max 2016\bin\assemblies\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;MAX2015</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>C:\Program Files\Autodesk\3ds Max 2013\bin\assemblies\</OutputPath>
+    <DefineConstants>TRACE;MAX2015</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Autodesk.Max, Version=17.0.630.0, Culture=neutral, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\..\Repos\Babylon.js\Exporters\3ds Max\Max2Babylon\2015\Refs\Autodesk.Max.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="SharpDX, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\SharpDX.3.1.1\lib\net45\SharpDX.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="SharpDX.Mathematics, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\SharpDX.Mathematics.3.1.1\lib\net45\SharpDX.Mathematics.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Web" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\BabylonActionCallback.cs">
+      <Link>BabylonActionCallback.cs</Link>
+    </Compile>
+    <Compile Include="..\BabylonExportActionItem.cs">
+      <Link>BabylonExportActionItem.cs</Link>
+    </Compile>
+    <Compile Include="..\BabylonPropertiesActionItem.cs">
+      <Link>BabylonPropertiesActionItem.cs</Link>
+    </Compile>
+    <Compile Include="..\Descriptor.cs">
+      <Link>Descriptor.cs</Link>
+    </Compile>
+    <Compile Include="..\Exporter\ActionBuilder\BabylonActionsBuilderActionItem.cs">
+      <Link>Exporter\ActionBuilder\BabylonActionsBuilderActionItem.cs</Link>
+    </Compile>
+    <Compile Include="..\Exporter\ActionBuilder\BabylonExporter.Action.cs">
+      <Link>Exporter\ActionBuilder\BabylonExporter.Action.cs</Link>
+    </Compile>
+    <Compile Include="..\Exporter\BabylonExporter.Animation.cs">
+      <Link>Exporter\BabylonExporter.Animation.cs</Link>
+    </Compile>
+    <Compile Include="..\Exporter\BabylonExporter.Camera.cs">
+      <Link>Exporter\BabylonExporter.Camera.cs</Link>
+    </Compile>
+    <Compile Include="..\Exporter\BabylonExporter.cs">
+      <Link>Exporter\BabylonExporter.cs</Link>
+    </Compile>
+    <Compile Include="..\Exporter\BabylonExporter.Light.cs">
+      <Link>Exporter\BabylonExporter.Light.cs</Link>
+    </Compile>
+    <Compile Include="..\Exporter\BabylonExporter.Material.cs">
+      <Link>Exporter\BabylonExporter.Material.cs</Link>
+    </Compile>
+    <Compile Include="..\Exporter\BabylonExporter.Mesh.cs">
+      <Link>Exporter\BabylonExporter.Mesh.cs</Link>
+    </Compile>
+    <Compile Include="..\Exporter\BabylonExporter.ShadowGenerator.cs">
+      <Link>Exporter\BabylonExporter.ShadowGenerator.cs</Link>
+    </Compile>
+    <Compile Include="..\Exporter\BabylonExporter.Skeleton.cs">
+      <Link>Exporter\BabylonExporter.Skeleton.cs</Link>
+    </Compile>
+    <Compile Include="..\Exporter\BabylonExporter.Texture.cs">
+      <Link>Exporter\BabylonExporter.Texture.cs</Link>
+    </Compile>
+    <Compile Include="..\Exporter\GlobalVertex.cs">
+      <Link>Exporter\GlobalVertex.cs</Link>
+    </Compile>
+    <Compile Include="..\Forms\ActionsBuilderForm.cs">
+      <Link>Forms\ActionsBuilderForm.cs</Link>
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="..\Forms\ActionsBuilderForm.designer.cs">
+      <Link>Forms\ActionsBuilderForm.designer.cs</Link>
+      <DependentUpon>ActionsBuilderForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="..\Forms\CameraPropertiesForm.cs">
+      <Link>Forms\CameraPropertiesForm.cs</Link>
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="..\Forms\CameraPropertiesForm.Designer.cs">
+      <Link>Forms\CameraPropertiesForm.Designer.cs</Link>
+      <DependentUpon>CameraPropertiesForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="..\Forms\ExporterForm.cs">
+      <Link>Forms\ExporterForm.cs</Link>
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="..\Forms\ExporterForm.Designer.cs">
+      <Link>Forms\ExporterForm.Designer.cs</Link>
+      <DependentUpon>ExporterForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="..\Forms\LightPropertiesForm.cs">
+      <Link>Forms\LightPropertiesForm.cs</Link>
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="..\Forms\LightPropertiesForm.Designer.cs">
+      <Link>Forms\LightPropertiesForm.Designer.cs</Link>
+      <DependentUpon>LightPropertiesForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="..\Forms\ObjectPropertiesForm.cs">
+      <Link>Forms\ObjectPropertiesForm.cs</Link>
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="..\Forms\ObjectPropertiesForm.Designer.cs">
+      <Link>Forms\ObjectPropertiesForm.Designer.cs</Link>
+      <DependentUpon>ObjectPropertiesForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="..\Forms\ScenePropertiesForm.cs">
+      <Link>Forms\ScenePropertiesForm.cs</Link>
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="..\Forms\ScenePropertiesForm.Designer.cs">
+      <Link>Forms\ScenePropertiesForm.Designer.cs</Link>
+      <DependentUpon>ScenePropertiesForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="..\Forms\Vector3Control.cs">
+      <Link>Forms\Vector3Control.cs</Link>
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="..\Forms\Vector3Control.Designer.cs">
+      <Link>Forms\Vector3Control.Designer.cs</Link>
+      <DependentUpon>Vector3Control.cs</DependentUpon>
+    </Compile>
+    <Compile Include="..\GlobalUtility.cs">
+      <Link>GlobalUtility.cs</Link>
+    </Compile>
+    <Compile Include="..\JsonTextWriterOptimized.cs">
+      <Link>JsonTextWriterOptimized.cs</Link>
+    </Compile>
+    <Compile Include="..\Loader.cs">
+      <Link>Loader.cs</Link>
+    </Compile>
+    <Compile Include="..\Tools\Tools.cs">
+      <Link>Tools\Tools.cs</Link>
+    </Compile>
+    <Compile Include="..\Tools\VNormal.cs">
+      <Link>Tools\VNormal.cs</Link>
+    </Compile>
+    <Compile Include="..\Tools\WebServer.cs">
+      <Link>Tools\WebServer.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Refs\Autodesk.Max.dll" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="..\Forms\ActionsBuilderForm.resx">
+      <Link>Forms\ActionsBuilderForm.resx</Link>
+      <DependentUpon>ActionsBuilderForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="..\Forms\CameraPropertiesForm.resx">
+      <Link>Forms\CameraPropertiesForm.resx</Link>
+      <DependentUpon>CameraPropertiesForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="..\Forms\ExporterForm.resx">
+      <Link>Forms\ExporterForm.resx</Link>
+      <DependentUpon>ExporterForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="..\Forms\LightPropertiesForm.resx">
+      <Link>Forms\LightPropertiesForm.resx</Link>
+      <DependentUpon>LightPropertiesForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="..\Forms\ObjectPropertiesForm.resx">
+      <Link>Forms\ObjectPropertiesForm.resx</Link>
+      <DependentUpon>ObjectPropertiesForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="..\Forms\ScenePropertiesForm.resx">
+      <Link>Forms\ScenePropertiesForm.resx</Link>
+      <DependentUpon>ScenePropertiesForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="..\Forms\Vector3Control.resx">
+      <Link>Forms\Vector3Control.resx</Link>
+      <DependentUpon>Vector3Control.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\BabylonExport.Entities\BabylonExport.Entities.csproj">
+      <Project>{6150965a-658c-4263-89ad-4f980eb0675d}</Project>
+      <Name>BabylonExport.Entities</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\BabylonFileConverter\BabylonFileConverter.csproj">
+      <Project>{a6b76356-1d1c-4c82-8199-a6406da85a95}</Project>
+      <Name>BabylonFileConverter</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <WCFMetadata Include="Service References\" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PostBuildEvent>mkdir "$(OutDir)BabylonActionsBuilder"
+mkdir "$(OutDir)BabylonActionsBuilder\fonts"
+mkdir "$(OutDir)BabylonActionsBuilder\fonts\SinkinSans"
+copy "$(SolutionDir)ActionsBuilder\Sources\fonts.css" "$(OutDir)BabylonActionsBuilder\fonts.css"
+copy "$(SolutionDir)ActionsBuilder\Sources\index.css" "$(OutDir)BabylonActionsBuilder\index.css"
+copy "$(SolutionDir)ActionsBuilder\Sources\index.html" "$(OutDir)BabylonActionsBuilder\index.html"
+copy "$(SolutionDir)ActionsBuilder\Sources\actionsbuilder.max.js" "$(OutDir)BabylonActionsBuilder\actionsbuilder.max.js"
+copy "$(SolutionDir)ActionsBuilder\Sources\raphael.js" "$(OutDir)BabylonActionsBuilder\raphael.js"
+copy "$(SolutionDir)babylon.max.js" "$(OutDir)BabylonActionsBuilder\babylon.max.js"
+copy "$(SolutionDir)ActionsBuilder\Sources\fonts\SinkinSans\" "$(OutDir)BabylonActionsBuilder\fonts\SinkinSans\"</PostBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
 </Project>

+ 36 - 36
Exporters/3ds Max/Max2Babylon/2015/Properties/AssemblyInfo.cs

@@ -1,36 +1,36 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Max2Babylon")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Max2Babylon")]
-[assembly: AssemblyCopyright("Copyright ©  2014")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("2d621b1c-3661-49bd-8dd3-4c5de51fce94")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers 
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Max2Babylon")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Max2Babylon")]
+[assembly: AssemblyCopyright("Copyright ©  2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("2d621b1c-3661-49bd-8dd3-4c5de51fce94")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 63 - 63
Exporters/3ds Max/Max2Babylon/2015/Properties/Resources.Designer.cs

@@ -1,63 +1,63 @@
-//------------------------------------------------------------------------------
-// <auto-generated>
-//     This code was generated by a tool.
-//     Runtime Version:4.0.30319.34014
-//
-//     Changes to this file may cause incorrect behavior and will be lost if
-//     the code is regenerated.
-// </auto-generated>
-//------------------------------------------------------------------------------
-
-namespace Max2Babylon.Properties {
-    using System;
-    
-    
-    /// <summary>
-    ///   A strongly-typed resource class, for looking up localized strings, etc.
-    /// </summary>
-    // This class was auto-generated by the StronglyTypedResourceBuilder
-    // class via a tool like ResGen or Visual Studio.
-    // To add or remove a member, edit your .ResX file then rerun ResGen
-    // with the /str option, or rebuild your VS project.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    internal class Resources {
-        
-        private static global::System.Resources.ResourceManager resourceMan;
-        
-        private static global::System.Globalization.CultureInfo resourceCulture;
-        
-        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
-        internal Resources() {
-        }
-        
-        /// <summary>
-        ///   Returns the cached ResourceManager instance used by this class.
-        /// </summary>
-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
-        internal static global::System.Resources.ResourceManager ResourceManager {
-            get {
-                if (object.ReferenceEquals(resourceMan, null)) {
-                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Max2Babylon.Properties.Resources", typeof(Resources).Assembly);
-                    resourceMan = temp;
-                }
-                return resourceMan;
-            }
-        }
-        
-        /// <summary>
-        ///   Overrides the current thread's CurrentUICulture property for all
-        ///   resource lookups using this strongly typed resource class.
-        /// </summary>
-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
-        internal static global::System.Globalization.CultureInfo Culture {
-            get {
-                return resourceCulture;
-            }
-            set {
-                resourceCulture = value;
-            }
-        }
-    }
-}
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.34014
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Max2Babylon.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Max2Babylon.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}

+ 119 - 119
Exporters/3ds Max/Max2Babylon/2015/Properties/Resources.resx

@@ -1,120 +1,120 @@
-<?xml version="1.0" encoding="utf-8"?>
-<root>
-  <!-- 
-    Microsoft ResX Schema 
-    
-    Version 2.0
-    
-    The primary goals of this format is to allow a simple XML format 
-    that is mostly human readable. The generation and parsing of the 
-    various data types are done through the TypeConverter classes 
-    associated with the data types.
-    
-    Example:
-    
-    ... ado.net/XML headers & schema ...
-    <resheader name="resmimetype">text/microsoft-resx</resheader>
-    <resheader name="version">2.0</resheader>
-    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
-    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
-    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
-    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
-    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
-        <value>[base64 mime encoded serialized .NET Framework object]</value>
-    </data>
-    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
-        <comment>This is a comment</comment>
-    </data>
-                
-    There are any number of "resheader" rows that contain simple 
-    name/value pairs.
-    
-    Each data row contains a name, and value. The row also contains a 
-    type or mimetype. Type corresponds to a .NET class that support 
-    text/value conversion through the TypeConverter architecture. 
-    Classes that don't support this are serialized and stored with the 
-    mimetype set.
-    
-    The mimetype is used for serialized objects, and tells the 
-    ResXResourceReader how to depersist the object. This is currently not 
-    extensible. For a given mimetype the value must be set accordingly:
-    
-    Note - application/x-microsoft.net.object.binary.base64 is the format 
-    that the ResXResourceWriter will generate, however the reader can 
-    read any of the formats listed below.
-    
-    mimetype: application/x-microsoft.net.object.binary.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
-            : and then encoded with base64 encoding.
-    
-    mimetype: application/x-microsoft.net.object.soap.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
-            : and then encoded with base64 encoding.
-
-    mimetype: application/x-microsoft.net.object.bytearray.base64
-    value   : The object must be serialized into a byte array 
-            : using a System.ComponentModel.TypeConverter
-            : and then encoded with base64 encoding.
-    -->
-  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
-    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
-    <xsd:element name="root" msdata:IsDataSet="true">
-      <xsd:complexType>
-        <xsd:choice maxOccurs="unbounded">
-          <xsd:element name="metadata">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" />
-              </xsd:sequence>
-              <xsd:attribute name="name" use="required" type="xsd:string" />
-              <xsd:attribute name="type" type="xsd:string" />
-              <xsd:attribute name="mimetype" type="xsd:string" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="assembly">
-            <xsd:complexType>
-              <xsd:attribute name="alias" type="xsd:string" />
-              <xsd:attribute name="name" type="xsd:string" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="data">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
-              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
-              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="resheader">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" />
-            </xsd:complexType>
-          </xsd:element>
-        </xsd:choice>
-      </xsd:complexType>
-    </xsd:element>
-  </xsd:schema>
-  <resheader name="resmimetype">
-    <value>text/microsoft-resx</value>
-  </resheader>
-  <resheader name="version">
-    <value>2.0</value>
-  </resheader>
-  <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
 </root>

+ 6 - 0
Exporters/3ds Max/Max2Babylon/2015/packages.config

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
+  <package id="SharpDX" version="3.1.1" targetFramework="net45" />
+  <package id="SharpDX.Mathematics" version="3.1.1" targetFramework="net45" />
+</packages>

+ 9 - 12
Exporters/3ds Max/Max2Babylon/2017/Max2Babylon2017.csproj

@@ -45,13 +45,17 @@
       <HintPath>..\..\..\..\..\Repos\Babylon.js\Exporters\3ds Max\Max2Babylon\2015\Refs\Autodesk.Max.dll</HintPath>
       <Private>False</Private>
     </Reference>
-    <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+    <Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
       <Private>True</Private>
     </Reference>
-    <Reference Include="SharpDX, Version=2.4.2.0, Culture=neutral, PublicKeyToken=627a3d6d1956f55a, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\..\BabylonExport.Core\Refs\SharpDX.dll</HintPath>
+    <Reference Include="SharpDX, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\SharpDX.3.1.1\lib\net45\SharpDX.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="SharpDX.Mathematics, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\SharpDX.Mathematics.3.1.1\lib\net45\SharpDX.Mathematics.dll</HintPath>
+      <Private>True</Private>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
@@ -248,13 +252,6 @@
     <None Include="packages.config" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
-  </Target>
   <PropertyGroup>
     <PostBuildEvent>mkdir "$(OutDir)BabylonActionsBuilder"
 mkdir "$(OutDir)BabylonActionsBuilder\fonts"

+ 6 - 0
Exporters/3ds Max/Max2Babylon/2017/packages.config

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
+  <package id="SharpDX" version="3.1.1" targetFramework="net45" />
+  <package id="SharpDX.Mathematics" version="3.1.1" targetFramework="net45" />
+</packages>

+ 0 - 80
Exporters/3ds Max/Max2Babylon/BabylonActionsBuilderActionItem.cs

@@ -1,80 +0,0 @@
-using Autodesk.Max;
-using ActionItem = Autodesk.Max.Plugins.ActionItem;
-
-namespace Max2Babylon
-{
-    public class BabylonActionsBuilderActionItem : ActionItem
-    {
-        public override bool ExecuteAction()
-        {
-            if (Loader.Core.SelNodeCount > 1)
-            {
-                Loader.Core.PushPrompt("Actions Builder only supports one Node");
-            }
-            else
-            {
-                IINode node = null;
-                SClass_ID type;
-
-                if (Loader.Core.SelNodeCount == 0)
-                    type = SClass_ID.Scene;
-                else
-                {
-                    node = Loader.Core.GetSelNode(0);
-                    type = node.ObjectRef.Eval(0).Obj.SuperClassID;
-                }
-
-                if (type == SClass_ID.Geomobject || type == SClass_ID.Light || type == SClass_ID.Camera || type == SClass_ID.Scene)
-                {
-                    using (var ab = new ActionsBuilderForm())
-                    {
-                        // Just show dialog
-                        ab.ShowDialog();
-                    }
-                }
-            }
-
-            return true;
-        }
-
-        public override int Id_
-        {
-            get { return 2; }
-        }
-
-        public override string ButtonText
-        {
-            get { return "Babylon Actions Builder"; }
-        }
-
-        public override string MenuText
-        {
-            get { return "Babylon Actions Builder"; }
-        }
-
-        public override string DescriptionText
-        {
-            get { return "UI graph to build custom actions on selected object"; }
-        }
-
-        public override string CategoryText
-        {
-            get { return "Babylon"; }
-        }
-
-        public override bool IsChecked_
-        {
-            get { return false; }
-        }
-
-        public override bool IsItemVisible
-        {
-            get { return true; }
-        }
-
-        public override bool IsEnabled_
-        {
-            get { return true; }
-        }
-    }
-}

+ 95 - 95
Exporters/3ds Max/Max2Babylon/Exporter/ActionBuilder/BabylonActionsBuilderActionItem.cs

@@ -1,95 +1,95 @@
-using Autodesk.Max;
-using System.Windows.Forms;
-using ActionItem = Autodesk.Max.Plugins.ActionItem;
-
-namespace Max2Babylon
-{
-    public class BabylonActionsBuilderActionItem : ActionItem
-    {
-        private ActionsBuilderForm _form = null;
-
-        public override bool ExecuteAction()
-        {
-            if (Loader.Core.SelNodeCount > 1)
-            {
-                Loader.Core.PushPrompt("Actions Builder only supports one Node");
-            }
-            else
-            {
-                IINode node = null;
-                SClass_ID type;
-
-                if (Loader.Core.SelNodeCount == 0)
-                    type = SClass_ID.Scene;
-                else
-                {
-                    node = Loader.Core.GetSelNode(0);
-                    type = node.ObjectRef.Eval(0).Obj.SuperClassID;
-                }
-
-                if (type == SClass_ID.Geomobject || type == SClass_ID.Scene)
-                {
-                    if (_form == null)
-                        _form = new ActionsBuilderForm(this);
-
-                    _form.WindowState = FormWindowState.Maximized;
-
-                    _form.ShowDialog();
-                    //Application.Run(_form);
-
-                }
-            }
-
-            return true;
-        }
-
-        public void Close()
-        {
-            if (_form == null)
-                return;
-
-            _form.Dispose();
-            _form = null;
-        }
-
-        public override int Id_
-        {
-            get { return 2; }
-        }
-
-        public override string ButtonText
-        {
-            get { return "Babylon Actions Builder"; }
-        }
-
-        public override string MenuText
-        {
-            get { return "Babylon Actions Builder"; }
-        }
-
-        public override string DescriptionText
-        {
-            get { return "UI graph to build custom actions on selected object"; }
-        }
-
-        public override string CategoryText
-        {
-            get { return "Babylon"; }
-        }
-
-        public override bool IsChecked_
-        {
-            get { return false; }
-        }
-
-        public override bool IsItemVisible
-        {
-            get { return true; }
-        }
-
-        public override bool IsEnabled_
-        {
-            get { return true; }
-        }
-    }
-}
+using Autodesk.Max;
+using System.Windows.Forms;
+using ActionItem = Autodesk.Max.Plugins.ActionItem;
+
+namespace Max2Babylon
+{
+    public class BabylonActionsBuilderActionItem : ActionItem
+    {
+        private ActionsBuilderForm _form = null;
+
+        public override bool ExecuteAction()
+        {
+            if (Loader.Core.SelNodeCount > 1)
+            {
+                Loader.Core.PushPrompt("Actions Builder only supports one Node");
+            }
+            else
+            {
+                IINode node = null;
+                SClass_ID type;
+
+                if (Loader.Core.SelNodeCount == 0)
+                    type = SClass_ID.Scene;
+                else
+                {
+                    node = Loader.Core.GetSelNode(0);
+                    type = node.ObjectRef.Eval(0).Obj.SuperClassID;
+                }
+
+                if (type == SClass_ID.Geomobject || type == SClass_ID.Scene)
+                {
+                    if (_form == null)
+                        _form = new ActionsBuilderForm(this);
+
+                    _form.WindowState = FormWindowState.Maximized;
+
+                    _form.ShowDialog();
+                    //Application.Run(_form);
+
+                }
+            }
+
+            return true;
+        }
+
+        public void Close()
+        {
+            if (_form == null)
+                return;
+
+            _form.Dispose();
+            _form = null;
+        }
+
+        public override int Id_
+        {
+            get { return 2; }
+        }
+
+        public override string ButtonText
+        {
+            get { return "Babylon Actions Builder"; }
+        }
+
+        public override string MenuText
+        {
+            get { return "Babylon Actions Builder"; }
+        }
+
+        public override string DescriptionText
+        {
+            get { return "UI graph to build custom actions on selected object"; }
+        }
+
+        public override string CategoryText
+        {
+            get { return "Babylon"; }
+        }
+
+        public override bool IsChecked_
+        {
+            get { return false; }
+        }
+
+        public override bool IsItemVisible
+        {
+            get { return true; }
+        }
+
+        public override bool IsEnabled_
+        {
+            get { return true; }
+        }
+    }
+}

+ 27 - 27
Exporters/3ds Max/Max2Babylon/Exporter/ActionBuilder/BabylonExporter.Action.cs

@@ -1,27 +1,27 @@
-using System;
-using System.Collections.Generic;
-using Newtonsoft.Json;
-using Autodesk.Max;
-using BabylonExport.Entities;
-
-namespace Max2Babylon
-{
-    partial class BabylonExporter
-    {
-        private BabylonActions ExportNodeAction(IIGameNode node)
-        {
-            string prop;
-            if (node != null)
-                prop = node.MaxNode.GetStringProperty("babylon_actionsbuilder", "");
-            else
-                prop = Loader.Core.RootNode.GetStringProperty("babylon_actionsbuilder", "");
-
-            if (String.IsNullOrEmpty(prop))
-                return null;
-
-            var result = JsonConvert.DeserializeObject<BabylonActions>(prop);
-
-            return result;
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using Autodesk.Max;
+using BabylonExport.Entities;
+
+namespace Max2Babylon
+{
+    partial class BabylonExporter
+    {
+        private BabylonActions ExportNodeAction(IIGameNode node)
+        {
+            string prop;
+            if (node != null)
+                prop = node.MaxNode.GetStringProperty("babylon_actionsbuilder", "");
+            else
+                prop = Loader.Core.RootNode.GetStringProperty("babylon_actionsbuilder", "");
+
+            if (String.IsNullOrEmpty(prop))
+                return null;
+
+            var result = JsonConvert.DeserializeObject<BabylonActions>(prop);
+
+            return result;
+        }
+    }
+}

+ 5 - 0
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Mesh.cs

@@ -490,6 +490,11 @@ namespace Max2Babylon
                     }
 
                     instance.scaling = new[] { instanceScale.X, instanceScale.Y, instanceScale.Z };
+
+                    if (instanceGameNode.NodeParent != null)
+                    {
+                        instance.parentId = GetParentID(instanceGameNode.NodeParent, babylonScene, scene);
+                    }
                 }
                 var instanceAnimations = new List<BabylonAnimation>();
                 GenerateCoordinatesAnimations(meshNode, instanceAnimations);

+ 208 - 187
Exporters/3ds Max/Max2Babylon/Max2Babylon.csproj

@@ -1,188 +1,209 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{DD7C931A-8FAF-4318-BB74-71DC858CC489}</ProjectGuid>
-    <OutputType>Library</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>Max2Babylon</RootNamespace>
-    <AssemblyName>Max2Babylon</AssemblyName>
-    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <TargetFrameworkProfile />
-    <SccProjectName>SAK</SccProjectName>
-    <SccLocalPath>SAK</SccLocalPath>
-    <SccAuxPath>SAK</SccAuxPath>
-    <SccProvider>SAK</SccProvider>
-    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
-    <NuGetPackageImportStamp>eeea6a2c</NuGetPackageImportStamp>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>C:\Program Files\Autodesk\3ds Max 2013\bin\assemblies\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <Prefer32Bit>false</Prefer32Bit>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>C:\Program Files\Autodesk\3ds Max 2013\bin\assemblies\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <Prefer32Bit>false</Prefer32Bit>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="Autodesk.Max, Version=15.6.164.0, Culture=neutral, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>Refs\Autodesk.Max.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
-    <Reference Include="BabylonFileConverter">
-      <HintPath>Refs\BabylonFileConverter.dll</HintPath>
-    </Reference>
-    <Reference Include="Newtonsoft.Json">
-      <HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>
-    </Reference>
-    <Reference Include="SharpDX, Version=2.4.2.0, Culture=neutral, PublicKeyToken=627a3d6d1956f55a, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>$(SharpDXPackageBinDir)\SharpDX.dll</HintPath>
-    </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Drawing" />
-    <Reference Include="System.Runtime.Serialization" />
-    <Reference Include="System.Web" />
-    <Reference Include="System.Windows.Forms" />
-    <Reference Include="System.Data.DataSetExtensions" />
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="BabylonActionCallback.cs" />
-    <Compile Include="BabylonPropertiesActionItem.cs" />
-    <Compile Include="Exporter\BabylonExporter.Skeleton.cs" />
-    <Compile Include="Forms\LightPropertiesForm.cs">
-      <SubType>Form</SubType>
-    </Compile>
-    <Compile Include="Forms\LightPropertiesForm.Designer.cs">
-      <DependentUpon>LightPropertiesForm.cs</DependentUpon>
-    </Compile>
-    <Compile Include="Exporter\BabylonExporter.Animation.cs" />
-    <Compile Include="Exporter\BabylonExporter.ShadowGenerator.cs" />
-    <Compile Include="Forms\CameraPropertiesForm.cs">
-      <SubType>Form</SubType>
-    </Compile>
-    <Compile Include="Forms\CameraPropertiesForm.Designer.cs">
-      <DependentUpon>CameraPropertiesForm.cs</DependentUpon>
-    </Compile>
-    <Compile Include="Descriptor.cs">
-      <SubType>Code</SubType>
-    </Compile>
-    <Compile Include="Forms\ExporterForm.cs">
-      <SubType>Form</SubType>
-    </Compile>
-    <Compile Include="Forms\ExporterForm.Designer.cs">
-      <DependentUpon>ExporterForm.cs</DependentUpon>
-    </Compile>
-    <Compile Include="Exporter\BabylonExporter.Texture.cs" />
-    <Compile Include="Exporter\BabylonExporter.Material.cs" />
-    <Compile Include="Exporter\BabylonExporter.Light.cs" />
-    <Compile Include="Exporter\BabylonExporter.cs" />
-    <Compile Include="Exporter\BabylonExporter.Camera.cs" />
-    <Compile Include="Exporter\BabylonExporter.Mesh.cs" />
-    <Compile Include="Exporter\GlobalVertex.cs" />
-    <Compile Include="GlobalUtility.cs" />
-    <Compile Include="JsonTextWriterOptimized.cs" />
-    <Compile Include="Loader.cs" />
-    <Compile Include="BabylonExportActionItem.cs" />
-    <Compile Include="Forms\ObjectPropertiesForm.cs">
-      <SubType>Form</SubType>
-    </Compile>
-    <Compile Include="Forms\ObjectPropertiesForm.Designer.cs">
-      <DependentUpon>ObjectPropertiesForm.cs</DependentUpon>
-    </Compile>
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Properties\Resources.Designer.cs">
-      <AutoGen>True</AutoGen>
-      <DesignTime>True</DesignTime>
-      <DependentUpon>Resources.resx</DependentUpon>
-    </Compile>
-    <Compile Include="Forms\ScenePropertiesForm.cs">
-      <SubType>Form</SubType>
-    </Compile>
-    <Compile Include="Forms\ScenePropertiesForm.Designer.cs">
-      <DependentUpon>ScenePropertiesForm.cs</DependentUpon>
-    </Compile>
-    <Compile Include="Tools\Tools.cs" />
-    <Compile Include="Forms\Vector3Control.cs">
-      <SubType>UserControl</SubType>
-    </Compile>
-    <Compile Include="Forms\Vector3Control.Designer.cs">
-      <DependentUpon>Vector3Control.cs</DependentUpon>
-    </Compile>
-    <Compile Include="Tools\VNormal.cs" />
-    <Compile Include="Tools\WebServer.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <Content Include="Refs\Autodesk.Max.dll" />
-    <Content Include="Refs\BabylonFileConverter.dll" />
-  </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Include="Forms\LightPropertiesForm.resx">
-      <DependentUpon>LightPropertiesForm.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="Forms\CameraPropertiesForm.resx">
-      <DependentUpon>CameraPropertiesForm.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="Forms\ExporterForm.resx">
-      <DependentUpon>ExporterForm.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="Forms\ObjectPropertiesForm.resx">
-      <DependentUpon>ObjectPropertiesForm.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="Properties\Resources.resx">
-      <Generator>ResXFileCodeGenerator</Generator>
-      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
-    </EmbeddedResource>
-    <EmbeddedResource Include="Forms\ScenePropertiesForm.resx">
-      <DependentUpon>ScenePropertiesForm.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="Forms\Vector3Control.resx">
-      <DependentUpon>Vector3Control.cs</DependentUpon>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\BabylonExport.Entities\BabylonExport.Entities.csproj">
-      <Project>{6150965a-658c-4263-89ad-4f980eb0675d}</Project>
-      <Name>BabylonExport.Entities</Name>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
-  </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <Import Project="..\packages\SharpDX.2.6.3\build\SharpDX.targets" Condition="Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" />
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SharpDX.2.6.3\build\SharpDX.targets'))" />
-  </Target>
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
-  -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{DD7C931A-8FAF-4318-BB74-71DC858CC489}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Max2Babylon</RootNamespace>
+    <AssemblyName>Max2Babylon</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+    <RestorePackages>true</RestorePackages>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>c:\Program Files\Autodesk\3ds Max 2013\bin\assemblies\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>C:\Program Files\Autodesk\3ds Max 2013\bin\assemblies\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Autodesk.Max, Version=15.6.164.0, Culture=neutral, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>Refs\Autodesk.Max.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="SharpDX">
+      <HintPath>..\packages\SharpDX.3.1.1\lib\net45\SharpDX.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="SharpDX.Mathematics">
+      <HintPath>..\packages\SharpDX.Mathematics.3.1.1\lib\net45\SharpDX.Mathematics.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Web" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="BabylonActionCallback.cs" />
+    <Compile Include="Exporter\ActionBuilder\BabylonActionsBuilderActionItem.cs" />
+    <Compile Include="BabylonPropertiesActionItem.cs" />
+    <Compile Include="Exporter\ActionBuilder\BabylonExporter.Action.cs" />
+    <Compile Include="Exporter\BabylonExporter.Skeleton.cs" />
+    <Compile Include="Forms\ActionsBuilderForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Forms\ActionsBuilderForm.Designer.cs">
+      <DependentUpon>ActionsBuilderForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Forms\LightPropertiesForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Forms\LightPropertiesForm.Designer.cs">
+      <DependentUpon>LightPropertiesForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Exporter\BabylonExporter.Animation.cs" />
+    <Compile Include="Exporter\BabylonExporter.ShadowGenerator.cs" />
+    <Compile Include="Forms\CameraPropertiesForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Forms\CameraPropertiesForm.Designer.cs">
+      <DependentUpon>CameraPropertiesForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Descriptor.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Forms\ExporterForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Forms\ExporterForm.Designer.cs">
+      <DependentUpon>ExporterForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Exporter\BabylonExporter.Texture.cs" />
+    <Compile Include="Exporter\BabylonExporter.Material.cs" />
+    <Compile Include="Exporter\BabylonExporter.Light.cs" />
+    <Compile Include="Exporter\BabylonExporter.cs" />
+    <Compile Include="Exporter\BabylonExporter.Camera.cs" />
+    <Compile Include="Exporter\BabylonExporter.Mesh.cs" />
+    <Compile Include="Exporter\GlobalVertex.cs" />
+    <Compile Include="GlobalUtility.cs" />
+    <Compile Include="JsonTextWriterOptimized.cs" />
+    <Compile Include="Loader.cs" />
+    <Compile Include="BabylonExportActionItem.cs" />
+    <Compile Include="Forms\ObjectPropertiesForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Forms\ObjectPropertiesForm.Designer.cs">
+      <DependentUpon>ObjectPropertiesForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Compile Include="Forms\ScenePropertiesForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Forms\ScenePropertiesForm.Designer.cs">
+      <DependentUpon>ScenePropertiesForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Tools\Tools.cs" />
+    <Compile Include="Forms\Vector3Control.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Forms\Vector3Control.Designer.cs">
+      <DependentUpon>Vector3Control.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Tools\VNormal.cs" />
+    <Compile Include="Tools\WebServer.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Refs\Autodesk.Max.dll" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Forms\ActionsBuilderForm.resx">
+      <DependentUpon>ActionsBuilderForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Forms\LightPropertiesForm.resx">
+      <DependentUpon>LightPropertiesForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Forms\CameraPropertiesForm.resx">
+      <DependentUpon>CameraPropertiesForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Forms\ExporterForm.resx">
+      <DependentUpon>ExporterForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Forms\ObjectPropertiesForm.resx">
+      <DependentUpon>ObjectPropertiesForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Forms\ScenePropertiesForm.resx">
+      <DependentUpon>ScenePropertiesForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Forms\Vector3Control.resx">
+      <DependentUpon>Vector3Control.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\BabylonExport.Entities\BabylonExport.Entities.csproj">
+      <Project>{6150965a-658c-4263-89ad-4f980eb0675d}</Project>
+      <Name>BabylonExport.Entities</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\BabylonFileConverter\BabylonFileConverter.csproj">
+      <Project>{a6b76356-1d1c-4c82-8199-a6406da85a95}</Project>
+      <Name>BabylonFileConverter</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PostBuildEvent>mkdir "$(OutDir)BabylonActionsBuilder"
+mkdir "$(OutDir)BabylonActionsBuilder\fonts"
+mkdir "$(OutDir)BabylonActionsBuilder\fonts\SinkinSans"
+copy "$(SolutionDir)ActionsBuilder\Sources\fonts.css" "$(OutDir)BabylonActionsBuilder\fonts.css"
+copy "$(SolutionDir)ActionsBuilder\Sources\index.css" "$(OutDir)BabylonActionsBuilder\index.css"
+copy "$(SolutionDir)ActionsBuilder\Sources\index.html" "$(OutDir)BabylonActionsBuilder\index.html"
+copy "$(SolutionDir)ActionsBuilder\Sources\actionsbuilder.max.js" "$(OutDir)BabylonActionsBuilder\actionsbuilder.max.js"
+copy "$(SolutionDir)ActionsBuilder\Sources\raphael.js" "$(OutDir)BabylonActionsBuilder\raphael.js"
+copy "$(SolutionDir)babylon.max.js" "$(OutDir)BabylonActionsBuilder\babylon.max.js"
+copy "$(SolutionDir)ActionsBuilder\Sources\fonts\SinkinSans\" "$(OutDir)BabylonActionsBuilder\fonts\SinkinSans\"</PostBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
 </Project>

+ 36 - 36
Exporters/3ds Max/Max2Babylon/Properties/AssemblyInfo.cs

@@ -1,36 +1,36 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Max2Babylon")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Max2Babylon")]
-[assembly: AssemblyCopyright("Copyright ©  2014")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("2d621b1c-3661-49bd-8dd3-4c5de51fce94")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers 
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Max2Babylon")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Max2Babylon")]
+[assembly: AssemblyCopyright("Copyright ©  2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("2d621b1c-3661-49bd-8dd3-4c5de51fce94")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 63 - 63
Exporters/3ds Max/Max2Babylon/Properties/Resources.Designer.cs

@@ -1,63 +1,63 @@
-//------------------------------------------------------------------------------
-// <auto-generated>
-//     This code was generated by a tool.
-//     Runtime Version:4.0.30319.34014
-//
-//     Changes to this file may cause incorrect behavior and will be lost if
-//     the code is regenerated.
-// </auto-generated>
-//------------------------------------------------------------------------------
-
-namespace Max2Babylon.Properties {
-    using System;
-    
-    
-    /// <summary>
-    ///   A strongly-typed resource class, for looking up localized strings, etc.
-    /// </summary>
-    // This class was auto-generated by the StronglyTypedResourceBuilder
-    // class via a tool like ResGen or Visual Studio.
-    // To add or remove a member, edit your .ResX file then rerun ResGen
-    // with the /str option, or rebuild your VS project.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    internal class Resources {
-        
-        private static global::System.Resources.ResourceManager resourceMan;
-        
-        private static global::System.Globalization.CultureInfo resourceCulture;
-        
-        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
-        internal Resources() {
-        }
-        
-        /// <summary>
-        ///   Returns the cached ResourceManager instance used by this class.
-        /// </summary>
-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
-        internal static global::System.Resources.ResourceManager ResourceManager {
-            get {
-                if (object.ReferenceEquals(resourceMan, null)) {
-                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Max2Babylon.Properties.Resources", typeof(Resources).Assembly);
-                    resourceMan = temp;
-                }
-                return resourceMan;
-            }
-        }
-        
-        /// <summary>
-        ///   Overrides the current thread's CurrentUICulture property for all
-        ///   resource lookups using this strongly typed resource class.
-        /// </summary>
-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
-        internal static global::System.Globalization.CultureInfo Culture {
-            get {
-                return resourceCulture;
-            }
-            set {
-                resourceCulture = value;
-            }
-        }
-    }
-}
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.34014
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Max2Babylon.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Max2Babylon.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}

+ 119 - 119
Exporters/3ds Max/Max2Babylon/Properties/Resources.resx

@@ -1,120 +1,120 @@
-<?xml version="1.0" encoding="utf-8"?>
-<root>
-  <!-- 
-    Microsoft ResX Schema 
-    
-    Version 2.0
-    
-    The primary goals of this format is to allow a simple XML format 
-    that is mostly human readable. The generation and parsing of the 
-    various data types are done through the TypeConverter classes 
-    associated with the data types.
-    
-    Example:
-    
-    ... ado.net/XML headers & schema ...
-    <resheader name="resmimetype">text/microsoft-resx</resheader>
-    <resheader name="version">2.0</resheader>
-    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
-    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
-    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
-    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
-    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
-        <value>[base64 mime encoded serialized .NET Framework object]</value>
-    </data>
-    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
-        <comment>This is a comment</comment>
-    </data>
-                
-    There are any number of "resheader" rows that contain simple 
-    name/value pairs.
-    
-    Each data row contains a name, and value. The row also contains a 
-    type or mimetype. Type corresponds to a .NET class that support 
-    text/value conversion through the TypeConverter architecture. 
-    Classes that don't support this are serialized and stored with the 
-    mimetype set.
-    
-    The mimetype is used for serialized objects, and tells the 
-    ResXResourceReader how to depersist the object. This is currently not 
-    extensible. For a given mimetype the value must be set accordingly:
-    
-    Note - application/x-microsoft.net.object.binary.base64 is the format 
-    that the ResXResourceWriter will generate, however the reader can 
-    read any of the formats listed below.
-    
-    mimetype: application/x-microsoft.net.object.binary.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
-            : and then encoded with base64 encoding.
-    
-    mimetype: application/x-microsoft.net.object.soap.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
-            : and then encoded with base64 encoding.
-
-    mimetype: application/x-microsoft.net.object.bytearray.base64
-    value   : The object must be serialized into a byte array 
-            : using a System.ComponentModel.TypeConverter
-            : and then encoded with base64 encoding.
-    -->
-  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
-    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
-    <xsd:element name="root" msdata:IsDataSet="true">
-      <xsd:complexType>
-        <xsd:choice maxOccurs="unbounded">
-          <xsd:element name="metadata">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" />
-              </xsd:sequence>
-              <xsd:attribute name="name" use="required" type="xsd:string" />
-              <xsd:attribute name="type" type="xsd:string" />
-              <xsd:attribute name="mimetype" type="xsd:string" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="assembly">
-            <xsd:complexType>
-              <xsd:attribute name="alias" type="xsd:string" />
-              <xsd:attribute name="name" type="xsd:string" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="data">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
-              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
-              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="resheader">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" />
-            </xsd:complexType>
-          </xsd:element>
-        </xsd:choice>
-      </xsd:complexType>
-    </xsd:element>
-  </xsd:schema>
-  <resheader name="resmimetype">
-    <value>text/microsoft-resx</value>
-  </resheader>
-  <resheader name="version">
-    <value>2.0</value>
-  </resheader>
-  <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
 </root>

二進制
Exporters/3ds Max/Max2Babylon/Refs/BabylonFileConverter.dll


二進制
Exporters/3ds Max/Max2Babylon/Refs/Newtonsoft.Json.dll


二進制
Exporters/3ds Max/Max2Babylon/Refs/SharpDX.dll


+ 1 - 0
Exporters/3ds Max/Max2Babylon/Tools/WebServer.cs

@@ -21,6 +21,7 @@ namespace Max2Babylon
     <script type='text/javascript' src='http://www.babylonjs.com/oimo.js'></script>
     <script type='text/javascript' src='http://www.babylonjs.com/cannon.js'></script>
     <script type='text/javascript' src='http://www.babylonjs.com/babylon.js'></script>
+    <script type='text/javascript' src='http://www.babylonjs.com/babylon.inspector.bundle.js'></script>
     <style type='text/css'>
         html, body, div, canvas {
             width: 100%;

+ 5 - 3
Exporters/3ds Max/Max2Babylon/packages.config

@@ -1,4 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
-  <package id="Newtonsoft.Json" version="6.0.7" targetFramework="net45" />
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
+  <package id="SharpDX" version="3.1.1" targetFramework="net45" />
+  <package id="SharpDX.Mathematics" version="3.1.1" targetFramework="net45" />
 </packages>

二進制
Exporters/3ds Max/Refs/Autodesk.Max.dll


+ 8 - 0
Exporters/Maya/Tools/babylonNameTool.mel

@@ -0,0 +1,8 @@
+global proc babylonNameTool() {
+    string $nameText;
+    string $resultPrompt = `promptDialog -title "Namespace Tool" -message "Remove Namespace:" -button "OK" -button "Cancel" -defaultButton "OK" -cancelButton "Cancel" -dismissString "Cancel"`;
+    if ($resultPrompt == "OK") {
+        $nameText = `promptDialog -query -text`;
+        namespace -mv $nameText ":" -force;
+    }
+}

+ 49 - 0
Exporters/Maya/Tools/babylonReskinTool.mel

@@ -0,0 +1,49 @@
+global proc reskinSelectedMeshes() {
+    $influencers = `intSliderGrp -q -value myReskinInfluencers`;
+    $selection = `ls -sl`;
+    $selected = size($selection);
+    if ($selected > 0) {
+        $skinName = `textFieldGrp -q -text myReskinName`;
+        if ($skinName != "") {
+            $textField_exists = `objExists $skinName`;
+            if ($textField_exists == 0) {
+                waitCursor -state 1;
+                $skinedCluster = $selection[0];
+                $skinnedJoints = `skinCluster -q -inf $skinedCluster`;
+                if ($selected > 1) {
+                    $duplicateObj = `duplicate $selection`;
+                    $createGrp = `group -n tempGroup`;
+                    $combine = `polyUnite -n $skinName $createGrp`;
+                    $deleteHistory = `delete -ch $combine`;
+                    delete $createGrp;
+                } else {
+                    $duplicateObj = `duplicate -n $skinName $selection`;
+                }
+                $jnt = `select -add $skinnedJoints $skinName`;
+                $selectionforBind = `ls -sl`;
+                $newskin = `skinCluster -mi $influencers $selectionforBind`;
+                $newSelect = `select -add $skinnedJoints $selection $skinName`;
+                $transfer = `copySkinWeights -nm -sa "closestPoint" -ia "closestJoint"`;
+                $cleared = `textFieldGrp -edit -text "" myReskinName`;
+                $deleted = `delete $selection`;
+                $deselect = `select -cl`;
+                waitCursor -state 0;
+            } else {
+                error ("Skin name is already in use: " + $skinName);
+            }
+        } else {
+            error "No name specified for re-skining.";
+        }
+    } else {
+        error "No meshes selected for re-skining.";
+    }
+}
+
+global proc babylonReskinTool() {
+    string $window = `window -title "Reskin Geometry Tool"`;
+    columnLayout -adjustableColumn true;
+    textFieldGrp -label "New Skin Name" -text "" myReskinName;
+    intSliderGrp -label "Max Influencers" -field true -minValue 1 -maxValue 8 -fieldMinValue 1 -fieldMaxValue 8 -value 4 myReskinInfluencers;
+    button -label "Reskin Selected Meshes" -command "reskinSelectedMeshes()" myReskinButton; 
+    showWindow $window;
+}

+ 36 - 0
Exporters/Maya/Tools/readme.md

@@ -0,0 +1,36 @@
+=========================================
+BabylonJS: Maya Art Tools
+=========================================
+1. Install Maya art tool scripts (.mel) in your scripts folder.
+   
+   Window Folder:
+   C:\Users\USERNAME\Documents\maya\*VERSION*\scripts
+   
+   Macintosh Folder:
+   ~/Library/Preferences/Autodesk/maya/*VERSION*/scripts
+
+
+===========================
+Add Namespace Tool To Shelf
+===========================
+*** Usage: Remove Unwanted Namespace From All Objects
+1. In Maya open the Script Editor and go to the Mel tab, copy and paste command below:
+########################
+
+babylonNameTool();
+
+########################
+2. Highlight it and click on "Save Script to Shelf...", specify a name ('Names') and click "OK".
+
+
+========================
+Add Reskin Tool To Shelf
+========================
+*** Usage: Reskin and combine selected meshes with new max influencers.
+1. In Maya open the Script Editor and go to the Mel tab, copy and paste command below:
+########################
+
+babylonReskinTool();
+
+########################
+2. Highlight it and click on "Save Script to Shelf...", specify a name ('Reskin') and click "OK".

+ 7 - 1
Tools/Gulp/config.json

@@ -208,7 +208,6 @@
       "../../src/PostProcess/babylon.lensRenderingPipeline.js",
       "../../src/PostProcess/babylon.colorCorrectionPostProcess.js",
       "../../src/Cameras/babylon.stereoscopicCameras.js",
-      "../../src/Cameras/Holographic/babylon.holographicCamera.js",
       "../../src/PostProcess/babylon.hdrRenderingPipeline.js",
       "../../src/Rendering/babylon.edgesRenderer.js",
       "../../src/PostProcess/babylon.tonemapPostProcess.js",
@@ -412,6 +411,13 @@
           "../../proceduralTexturesLibrary/src/starfield/starfieldProceduralTexture.fragment.fx"
         ],
         "output": "babylon.starfieldProceduralTexture.js"
+      },
+      {
+        "files": ["../../proceduralTexturesLibrary/src/normalMap/babylon.normalMapProceduralTexture.ts"],
+        "shaderFiles": [
+          "../../proceduralTexturesLibrary/src/normalMap/normalMapProceduralTexture.fragment.fx"
+        ],
+        "output": "babylon.normalMapProceduralTexture.js"
       }
     ],
     "build": {

+ 3 - 3
Tools/Gulp/package.json

@@ -8,10 +8,10 @@
   "license": "(Apache-2.0)",
   "devDependencies": {
     "gulp": "^3.8.11",
-    "gulp-uglify": "~1.5.3",
+    "gulp-uglify": "^2.0.1",
     "gulp-sourcemaps": "~1.9.1",
-    "typescript": "^2.1.4",
-    "gulp-typescript": "^3.1.3",
+    "typescript": "~2.1.4",
+    "gulp-typescript": "^3.1.5",
     "through2": "~0.6.5",
     "gulp-util": "~3.0.4",
     "gulp-concat": "~2.5.2",

+ 28 - 36
canvas2D/src/Engine/babylon.atlasPicture.ts

@@ -208,46 +208,38 @@
          * @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;
+            Tools.LoadFile(url, (data) => {
+                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(data);
+                    if (ret) {
+                        if (ret.api) {
+                            ret.api.texture = texture;
+                            if (onLoad) {
+                                onLoad(ret.api);
                             }
+                        } else if (onError) {
+                            onError(ret.errorMsg, ret.errorCode);
                         }
-
-                        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);
-                        }
+                        return;
                     }
                 }
-            }
-            xhr.open("GET", url, true);
-            xhr.send();
+
+                if (onError) {
+                    onError("No plugin to load this Atlas Data file format", -1);
+                }
+            }, null, null, null, () => {
+                if (onError) {
+                    onError("Couldn't load file", -1);
+                }
+            });
             return null;
         }
 

+ 7 - 0
canvas2D/src/Engine/babylon.bounding2d.ts

@@ -153,6 +153,13 @@
             this._worldAABBDirty = true;
         }
 
+        public equals(other: BoundingInfo2D): boolean {
+            if (!other) {
+                return false;
+            }
+            return other.center.equals(this.center) && other.extent.equals(this.extent);
+        }
+
         /**
          * return the max extend of the bounding info
          */

+ 90 - 42
canvas2D/src/Engine/babylon.canvas2d.ts

@@ -87,18 +87,19 @@
         }) {
             super(settings);
 
-            this._drawCallsOpaqueCounter       = new PerfCounter();
-            this._drawCallsAlphaTestCounter    = new PerfCounter();
-            this._drawCallsTransparentCounter  = new PerfCounter();
-            this._groupRenderCounter           = new PerfCounter();
-            this._updateTransparentDataCounter = new PerfCounter();
-            this._cachedGroupRenderCounter     = new PerfCounter();
-            this._updateCachedStateCounter     = new PerfCounter();
-            this._updateLayoutCounter          = new PerfCounter();
-            this._updatePositioningCounter     = new PerfCounter();
-            this._updateLocalTransformCounter  = new PerfCounter();
-            this._updateGlobalTransformCounter = new PerfCounter();
-            this._boundingInfoRecomputeCounter = new PerfCounter();
+            this._drawCallsOpaqueCounter          = new PerfCounter();
+            this._drawCallsAlphaTestCounter       = new PerfCounter();
+            this._drawCallsTransparentCounter     = new PerfCounter();
+            this._groupRenderCounter              = new PerfCounter();
+            this._updateTransparentDataCounter    = new PerfCounter();
+            this._cachedGroupRenderCounter        = new PerfCounter();
+            this._updateCachedStateCounter        = new PerfCounter();
+            this._updateLayoutCounter             = new PerfCounter();
+            this._updatePositioningCounter        = new PerfCounter();
+            this._updateLocalTransformCounter     = new PerfCounter();
+            this._updateGlobalTransformCounter    = new PerfCounter();
+            this._boundingInfoRecomputeCounter    = new PerfCounter();
+            this._layoutBoundingInfoUpdateCounter = new PerfCounter();
 
             this._cachedCanvasGroup = null;
 
@@ -168,6 +169,8 @@
             this._scene = scene;
             this._engine = engine;
             this._renderingSize = new Size(0, 0);
+            this._curHWScale = 0;
+            this._canvasLevelScale = new Vector3(1, 1, 1);
             this._designSize = settings.designSize || null;
             this._designUseHorizAxis = settings.designUseHorizAxis === true;
             if (!this._trackedGroups) {
@@ -276,6 +279,10 @@
             return this._boundingInfoRecomputeCounter;
         }
 
+        public get layoutBoundingInfoUpdateCounter(): PerfCounter {
+            return this._layoutBoundingInfoUpdateCounter;
+        }
+
         public static get instances() : Array<Canvas2D> {
             return Canvas2D._INSTANCES;
         }
@@ -1134,6 +1141,7 @@
             this._updateLocalTransformCounter.fetchNewFrame();
             this._updateGlobalTransformCounter.fetchNewFrame();
             this._boundingInfoRecomputeCounter.fetchNewFrame();
+            this._layoutBoundingInfoUpdateCounter.fetchNewFrame();
         }
 
         private _fetchPerfMetrics() {
@@ -1149,6 +1157,7 @@
             this._updateLocalTransformCounter.addCount(0, true);
             this._updateGlobalTransformCounter.addCount(0, true);
             this._boundingInfoRecomputeCounter.addCount(0, true);
+            this._layoutBoundingInfoUpdateCounter.addCount(0, true);
         }
 
         private _updateProfileCanvas() {
@@ -1170,7 +1179,8 @@
                     ` - Update Positioning: ${this.updatePositioningCounter.current}, (avg:${format(this.updatePositioningCounter.lastSecAverage)}, t:${format(this.updatePositioningCounter.total)})\n` + 
                     ` - Update Local  Trans: ${this.updateLocalTransformCounter.current}, (avg:${format(this.updateLocalTransformCounter.lastSecAverage)}, t:${format(this.updateLocalTransformCounter.total)})\n` + 
                     ` - Update Global Trans: ${this.updateGlobalTransformCounter.current}, (avg:${format(this.updateGlobalTransformCounter.lastSecAverage)}, t:${format(this.updateGlobalTransformCounter.total)})\n` + 
-                    ` - BoundingInfo Recompute: ${this.boundingInfoRecomputeCounter.current}, (avg:${format(this.boundingInfoRecomputeCounter.lastSecAverage)}, t:${format(this.boundingInfoRecomputeCounter.total)})`;
+                    ` - BoundingInfo Recompute: ${this.boundingInfoRecomputeCounter.current}, (avg:${format(this.boundingInfoRecomputeCounter.lastSecAverage)}, t:${format(this.boundingInfoRecomputeCounter.total)})\n` +
+                    ` - LayoutBoundingInfo Recompute: ${this.layoutBoundingInfoUpdateCounter.current}, (avg:${format(this.layoutBoundingInfoUpdateCounter.lastSecAverage)}, t:${format(this.layoutBoundingInfoUpdateCounter.total)})` ;
             this._profileInfoText.text = p;
         }
 
@@ -1189,35 +1199,57 @@
         }
 
         public _addGroupRenderCount(count: number) {
-            this._groupRenderCounter.addCount(count, false);
+            if (this._groupRenderCounter) {
+                this._groupRenderCounter.addCount(count, false);
+            }
         }
 
         public _addUpdateTransparentDataCount(count: number) {
-            this._updateTransparentDataCounter.addCount(count, false);
+            if (this._updateTransparentDataCounter) {
+                this._updateTransparentDataCounter.addCount(count, false);
+            }
         }
 
         public addCachedGroupRenderCounter(count: number) {
-            this._cachedGroupRenderCounter.addCount(count, false);
+            if (this._cachedGroupRenderCounter) {
+                this._cachedGroupRenderCounter.addCount(count, false);
+            }
         }
 
         public addUpdateCachedStateCounter(count: number) {
-            this._updateCachedStateCounter.addCount(count, false);
+            if (this._updateCachedStateCounter) {
+                this._updateCachedStateCounter.addCount(count, false);
+            }
         }
 
         public addUpdateLayoutCounter(count: number) {
-            this._updateLayoutCounter.addCount(count, false);
+            if (this._updateLayoutCounter) {
+                this._updateLayoutCounter.addCount(count, false);
+            }
         }
 
         public addUpdatePositioningCounter(count: number) {
-            this._updatePositioningCounter.addCount(count, false);
+            if (this._updatePositioningCounter) {
+                this._updatePositioningCounter.addCount(count, false);
+            }
         }
 
         public addupdateLocalTransformCounter(count: number) {
-            this._updateLocalTransformCounter.addCount(count, false);
+            if (this._updateLocalTransformCounter) {
+                this._updateLocalTransformCounter.addCount(count, false);
+            }
         }
 
         public addUpdateGlobalTransformCounter(count: number) {
-            this._updateGlobalTransformCounter.addCount(count, false);
+            if (this._updateGlobalTransformCounter) {
+                this._updateGlobalTransformCounter.addCount(count, false);
+            }
+        }
+
+        public addLayoutBoundingInfoUpdateCounter(count: number) {
+            if (this._layoutBoundingInfoUpdateCounter) {
+                this._layoutBoundingInfoUpdateCounter.addCount(count, false);
+            }
         }
 
         private _renderObservable: Observable<Canvas2D>;
@@ -1262,20 +1294,23 @@
         private _designUseHorizAxis: boolean;
         public  _primitiveCollisionManager: PrimitiveCollisionManagerBase;
 
-        public _renderingSize: Size;
-
-        private _drawCallsOpaqueCounter      : PerfCounter;
-        private _drawCallsAlphaTestCounter   : PerfCounter;
-        private _drawCallsTransparentCounter : PerfCounter;
-        private _groupRenderCounter          : PerfCounter;
-        private _updateTransparentDataCounter: PerfCounter;
-        private _cachedGroupRenderCounter    : PerfCounter;
-        private _updateCachedStateCounter    : PerfCounter;
-        private _updateLayoutCounter         : PerfCounter;
-        private _updatePositioningCounter    : PerfCounter;
-        private _updateGlobalTransformCounter: PerfCounter;
-        private _updateLocalTransformCounter : PerfCounter;
-        private _boundingInfoRecomputeCounter: PerfCounter;
+        public _canvasLevelScale: Vector3;
+        public  _renderingSize: Size;
+        private _curHWScale;
+
+        private _drawCallsOpaqueCounter          : PerfCounter;
+        private _drawCallsAlphaTestCounter       : PerfCounter;
+        private _drawCallsTransparentCounter     : PerfCounter;
+        private _groupRenderCounter              : PerfCounter;
+        private _updateTransparentDataCounter    : PerfCounter;
+        private _cachedGroupRenderCounter        : PerfCounter;
+        private _updateCachedStateCounter        : PerfCounter;
+        private _updateLayoutCounter             : PerfCounter;
+        private _updatePositioningCounter        : PerfCounter;
+        private _updateGlobalTransformCounter    : PerfCounter;
+        private _updateLocalTransformCounter     : PerfCounter;
+        private _boundingInfoRecomputeCounter    : PerfCounter;
+        private _layoutBoundingInfoUpdateCounter : PerfCounter;
 
         private _profilingCanvas: Canvas2D;
         private _profileInfoText: Text2D;
@@ -1427,15 +1462,26 @@
                 return;
             }
 
+            // Detect a change of HWRendering scale
+            let hwsl = this.engine.getHardwareScalingLevel();
+            let hwslChanged = this._curHWScale !== hwsl;
+            if (hwslChanged) {
+                this._curHWScale = hwsl;
+                for (let child of this.children) {
+                    child._setFlags(SmartPropertyPrim.flagLocalTransformDirty|SmartPropertyPrim.flagGlobalTransformDirty);
+                }
+                this._setLayoutDirty();
+            }
+
             // Detect a change of rendering size
             let renderingSizeChanged = false;
-            let newWidth = this.engine.getRenderWidth();
+            let newWidth = this.engine.getRenderWidth() * hwsl;
             if (newWidth !== this._renderingSize.width) {
                 renderingSizeChanged = true;
             }
             this._renderingSize.width = newWidth;
 
-            let newHeight = this.engine.getRenderHeight();
+            let newHeight = this.engine.getRenderHeight() * hwsl;
             if (newHeight !== this._renderingSize.height) {
                 renderingSizeChanged = true;
             }
@@ -1443,7 +1489,6 @@
 
             // If the canvas fit the rendering size and it changed, update
             if (renderingSizeChanged && this._fitRenderingDevice) {
-                this.actualSize = this._renderingSize.clone();
                 this.size = this._renderingSize.clone();
                 if (this._background) {
                     this._background.size = this.size;
@@ -1457,18 +1502,21 @@
             if (this._designSize) {
                 let scale: number;
                 if (this._designUseHorizAxis) {
-                    scale = this._renderingSize.width / this._designSize.width;
+                    scale = this._renderingSize.width / (this._designSize.width * hwsl);
                 } else {
-                    scale = this._renderingSize.height / this._designSize.height;
+                    scale = this._renderingSize.height / (this._designSize.height * hwsl);
                 }
                 this.size = this._designSize.clone();
-                this.actualSize = this._designSize.clone();
-                this.scale = scale;
+                this._canvasLevelScale.copyFromFloats(scale, scale, 1);
+            } else if (this._curHWScale !== 1) {
+                let ratio = 1 / this._curHWScale;
+                this._canvasLevelScale.copyFromFloats(ratio, ratio, 1);
             }
 
             var context = new PrepareRender2DContext();
 
             ++this._globalTransformProcessStep;
+            this._setFlags(SmartPropertyPrim.flagLocalTransformDirty|SmartPropertyPrim.flagGlobalTransformDirty);
             this.updateCachedStates(false);
 
             this._prepareGroupRender(context);

+ 98 - 31
canvas2D/src/Engine/babylon.canvas2dLayoutEngine.ts

@@ -65,10 +65,10 @@
 
             // If this prim is layoutDiry we update  its layoutArea and also the one of its direct children
             if (prim._isFlagSet(SmartPropertyPrim.flagLayoutDirty)) {
+                prim._clearFlags(SmartPropertyPrim.flagLayoutDirty);
                 for (let child of prim.children) {
                     this._doUpdate(child);
                 }
-                prim._clearFlags(SmartPropertyPrim.flagLayoutDirty);
             }
 
         }
@@ -86,7 +86,12 @@
 
             // Indirect child of Canvas
             else {
-                prim.layoutArea = prim.parent.contentArea;
+                let contentArea = prim.parent.contentArea;
+
+                // Can be null if the parent's content area depend of its children, the computation will be done in many passes
+                if (contentArea) {
+                    prim.layoutArea = contentArea;
+                }
             }
         }
 
@@ -143,47 +148,89 @@
 
         private _isHorizontal: boolean = true;
 
+        private static stackPanelLayoutArea = Size.Zero();
         private static dstOffset = Vector4.Zero();
         private static dstArea = Size.Zero();
 
+        private static computeCounter = 0;
+
         public updateLayout(prim: Prim2DBase) {
             if (prim._isFlagSet(SmartPropertyPrim.flagLayoutDirty)) {
 
+                let primLayoutArea = prim.layoutArea;
+                let isSizeAuto = prim.isSizeAuto;
+
+                // If we're not in autoSize the layoutArea of the prim having the stack panel must be computed in order for us to compute the children' position.
+                // If there's at least one auto size (Horizontal or Vertical) we will have to figure the layoutArea ourselves
+                if (!primLayoutArea && !isSizeAuto) {
+                    return;
+                }
+
+//                console.log("Compute Stack Panel Layout " + ++StackPanelLayoutEngine.computeCounter);
+
                 let x = 0;
                 let y = 0;
-                let h = this.isHorizontal;
+                let horizonStackPanel = this.isHorizontal;
+
+                // If the stack panel is horizontal we check if the primitive height is auto or not, if it's auto then we have to compute the required height, otherwise we just take the actualHeight. If the stack panel is vertical we do the same but with width
                 let max = 0;
 
+                let stackPanelLayoutArea = StackPanelLayoutEngine.stackPanelLayoutArea;
+                if (horizonStackPanel) {
+                    if (prim.isVerticalSizeAuto) {
+                        max = 0;
+                        stackPanelLayoutArea.height = 0;
+                    } else {
+                        max = prim.layoutArea.height;
+                        stackPanelLayoutArea.height = prim.layoutArea.height;
+                        stackPanelLayoutArea.width = 0;
+                    }
+                } else {
+                    if (prim.isHorizontalSizeAuto) {
+                        max = 0;
+                        stackPanelLayoutArea.width = 0;
+                    } else {
+                        max = prim.layoutArea.width;
+                        stackPanelLayoutArea.width = prim.layoutArea.width;
+                        stackPanelLayoutArea.height = 0;
+                    }
+                }
+
                 for (let child of prim.children) {
                     if (child._isFlagSet(SmartPropertyPrim.flagNoPartOfLayout)) {
                         continue;
                     }
-                    let layoutArea: Size;
+
                     if (child._hasMargin) {
-                        child.margin.computeWithAlignment(prim.layoutArea, child.actualSize, child.marginAlignment, child.actualScale, StackPanelLayoutEngine.dstOffset, StackPanelLayoutEngine.dstArea, true);
-                        layoutArea = StackPanelLayoutEngine.dstArea.clone();
-                        child.layoutArea = layoutArea;
+
+                        // Calling computeWithAlignment will return us the area taken by "child" which is its layoutArea
+                        // We also have the dstOffset which will give us the y position in horizontal mode or x position in vertical mode.
+                        //  The alignment offset on the other axis is simply ignored as it doesn't make any sense (e.g. horizontal alignment is ignored in horizontal mode)
+                        child.margin.computeWithAlignment(stackPanelLayoutArea, child.actualSize, child.marginAlignment, child.actualScale, StackPanelLayoutEngine.dstOffset, StackPanelLayoutEngine.dstArea, true);
+
+                        child.layoutArea = StackPanelLayoutEngine.dstArea;
+
                     } else {
-                        layoutArea = child.layoutArea;
-                        child.margin.computeArea(child.actualSize, layoutArea);
+                        child.margin.computeArea(child.actualSize, child.actualScale, StackPanelLayoutEngine.dstArea);
+                        child.layoutArea = StackPanelLayoutEngine.dstArea;
                     }
 
-                    max = Math.max(max, h ? layoutArea.height : layoutArea.width);
-
+                    max = Math.max(max, horizonStackPanel ? StackPanelLayoutEngine.dstArea.height : StackPanelLayoutEngine.dstArea.width);
                 }
 
                 for (let child of prim.children) {
                     if (child._isFlagSet(SmartPropertyPrim.flagNoPartOfLayout)) {
                         continue;
                     }
-                    child.layoutAreaPos = new Vector2(x, y);
 
                     let layoutArea = child.layoutArea;
 
-                    if (h) {
+                    if (horizonStackPanel) {
+                        child.layoutAreaPos = new Vector2(x, 0);
                         x += layoutArea.width;
                         child.layoutArea = new Size(layoutArea.width, max);
                     } else {
+                        child.layoutAreaPos = new Vector2(0, y);
                         y += layoutArea.height;
                         child.layoutArea = new Size(max, layoutArea.height);
                     }
@@ -321,20 +368,25 @@
 
         private static dstOffset = Vector4.Zero();
         private static dstArea = Size.Zero();
+        private static dstAreaPos = Vector2.Zero();
 
         public updateLayout(prim: Prim2DBase) {
             if (prim._isFlagSet(SmartPropertyPrim.flagLayoutDirty)) {
 
+                if (!prim.layoutArea) {
+                    return;
+                }
+
                 for (let child of prim.children) {
                     if (child._isFlagSet(SmartPropertyPrim.flagNoPartOfLayout)) {
                         continue;
                     }
                     if (child._hasMargin) {
                         child.margin.computeWithAlignment(prim.layoutArea, child.actualSize, child.marginAlignment, child.actualScale, GridPanelLayoutEngine.dstOffset, GridPanelLayoutEngine.dstArea, true);
-                        child.layoutArea = GridPanelLayoutEngine.dstArea.clone();
                     } else {
-                        child.margin.computeArea(child.actualSize, child.layoutArea);
+                        child.margin.computeArea(child.actualSize, child.actualScale, GridPanelLayoutEngine.dstArea);
                     }
+                    child.layoutArea = GridPanelLayoutEngine.dstArea;
                 }
 
                 this._updateGrid(prim);
@@ -344,7 +396,8 @@
                 let cl = this._columns.length;
                 let columnWidth = 0;
                 let rowHeight = 0;
-                let layoutArea = new BABYLON.Size(0, 0);
+                let dstArea = GridPanelLayoutEngine.dstArea;
+                let dstAreaPos = GridPanelLayoutEngine.dstAreaPos;
 
                 for(let i = 0; i < _children.length; i++){
                     let children = _children[i];
@@ -382,13 +435,17 @@
                                     }
                                     
                                 }
+                                
+                                dstArea.width = columnWidth;
+                                dstArea.height = rowHeight;
 
-                                layoutArea.width = columnWidth;
-                                layoutArea.height = rowHeight;                                
-
-                                child.margin.computeWithAlignment(layoutArea, child.actualSize, child.marginAlignment, child.actualScale, GridPanelLayoutEngine.dstOffset, GridPanelLayoutEngine.dstArea);
-                                child.layoutAreaPos = new BABYLON.Vector2(left + GridPanelLayoutEngine.dstOffset.x, bottom + GridPanelLayoutEngine.dstOffset.y);
+                                child.layoutArea = dstArea;
                                 
+                                dstAreaPos.x = left;
+                                dstAreaPos.y = bottom;
+
+                                child.layoutAreaPos = dstAreaPos;
+
                                 bottom = oBottom;
                                 rowHeight = oRowHeight;
                                 
@@ -417,7 +474,7 @@
             let row = rows[rowNum];
             let maxHeight = 0;
 
-            if(children){
+            if(children && children[rowNum]){
 
                 for(let i = 0; i < cl; i++){
                     let child = children[rowNum][i];
@@ -448,11 +505,13 @@
             if(children){
 
                 for(let i = 0; i < rl; i++){
-                    let child = children[i][colNum];
-                    if(child){
-                        let span = (<GridData>child.layoutData).columnSpan;
-                        if(maxWidth < child.layoutArea.width/span){
-                            maxWidth = child.layoutArea.width/span;
+                    if(children[i]){
+                        let child = children[i][colNum];
+                        if(child){
+                            let span = (<GridData>child.layoutData).columnSpan;
+                            if(maxWidth < child.layoutArea.width/span){
+                                maxWidth = child.layoutArea.width/span;
+                            }
                         }
                     }
                 }
@@ -533,7 +592,8 @@
 
                 }else if(row.heightType == GridDimensionDefinition.Pixels){
 
-                    this._rowHeights[i] = row.heightPixels;
+                    let maxChildHeight = this._getMaxChildHeightInRow(i);
+                    this._rowHeights[i] = Math.max(row.heightPixels, maxChildHeight);
                     rowHeights += this._rowHeights[i];
 
                 }else if(row.heightType == GridDimensionDefinition.Stars){
@@ -556,7 +616,10 @@
 
                     let rowIndex = starIndexes[i];
 
-                    this._rowHeights[rowIndex] = (this._rows[rowIndex].height / totalStars) * remainingHeight;
+                    let starHeight = (this._rows[rowIndex].height / totalStars) * remainingHeight;
+                    let maxChildHeight = this._getMaxChildHeightInRow(i);
+
+                    this._rowHeights[rowIndex] = Math.max(starHeight, maxChildHeight);
 
                 }
             }
@@ -578,7 +641,8 @@
 
                 }else if(column.widthType == GridDimensionDefinition.Pixels){
 
-                    this._columnWidths[i] = column.widthPixels;
+                    let maxChildWidth = this._getMaxChildWidthInColumn(i);
+                    this._columnWidths[i] = Math.max(column.widthPixels, maxChildWidth);
                     columnWidths += this._columnWidths[i];
 
                 }else if(column.widthType == GridDimensionDefinition.Stars){
@@ -601,7 +665,10 @@
 
                     let columnIndex = starIndexes[i];
 
-                    this._columnWidths[columnIndex] = (this._columns[columnIndex].width / totalStars) * remainingWidth;
+                    let starWidth = (this._columns[columnIndex].width / totalStars) * remainingWidth;
+                    let maxChildWidth = this._getMaxChildWidthInColumn(i);
+
+                    this._columnWidths[columnIndex] = Math.max(starWidth, maxChildWidth);
 
                 }
             }

+ 1 - 16
canvas2D/src/Engine/babylon.ellipse2d.ts

@@ -168,21 +168,6 @@
         public static acutalSizeProperty: Prim2DPropInfo;
         public static subdivisionsProperty: Prim2DPropInfo;
 
-        @instanceLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 1, pi => Ellipse2D.acutalSizeProperty = pi, false, true)
-        /**
-         * Get/Set the size of the ellipse
-         */
-        public get actualSize(): Size {
-            if (this._actualSize) {
-                return this._actualSize;
-            }
-            return this.size;
-        }
-
-        public set actualSize(value: Size) {
-            this._actualSize = value;
-        }
-
         @modelLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 2, pi => Ellipse2D.subdivisionsProperty = pi)
         /**
          * Get/set the number of subdivisions used to draw the ellipsis. Default is 64.
@@ -289,7 +274,7 @@
             paddingLeft           ?: number | string,
             paddingRight          ?: number | string,
             paddingBottom         ?: number | string,
-            padding               ?: string,
+            padding               ?: number | string,
         }) {
 
             // Avoid checking every time if the object exists

+ 140 - 33
canvas2D/src/Engine/babylon.fontTexture.ts

@@ -14,6 +14,10 @@
          */
         bottomRightUV: Vector2;
 
+        xOffset: number;
+        yOffset: number;
+        xAdvance: number;
+
         charWidth: number;
     }
 
@@ -154,7 +158,8 @@
         textureSize : Size;
         atlasName   : string;
         padding     : Vector4;       // Left, Top, Right, Bottom
-        lineHeight: number;
+        lineHeight  : number;
+        baseLine    : number;
         textureUrl  : string;
         textureFile : string;
     }
@@ -331,6 +336,7 @@
         private _xMargin: number;
         private _yMargin: number;
         private _offset: number;
+        private _baseLine: number;
         private _currentFreePosition: Vector2;
         private _curCharCount = 0;
         private _lastUpdateCharCount = -1;
@@ -339,6 +345,7 @@
         private _sdfContext: CanvasRenderingContext2D;
         private _sdfScale: number;
         private _usedCounter = 1;
+        public debugMode: boolean;
 
         get isDynamicFontTexture(): boolean {
             return true;
@@ -389,6 +396,7 @@
             super(null, scene, true, false, samplingMode);
 
             this.name = name;
+            this.debugMode = false;
 
             this.wrapU = Texture.CLAMP_ADDRESSMODE;
             this.wrapV = Texture.CLAMP_ADDRESSMODE;
@@ -397,7 +405,7 @@
             this._signedDistanceField = signedDistanceField;
             this._superSample = false;
 
-            // SDF will use supersample no matter what, the resolution is otherwise too poor to produce correct result
+            // SDF will use super sample no matter what, the resolution is otherwise too poor to produce correct result
             if (superSample || signedDistanceField) {
                 let sfont = this.getSuperSampleFont(font);
                 if (sfont) {
@@ -413,19 +421,22 @@
             this._context.fillStyle = "white";
             this._context.textBaseline = "top";
 
-            var res = this.getFontHeight(font);
+            var res = this.getFontHeight(font, "j$|");
             this._lineHeightSuper = res.height; //+4;
             this._lineHeight = this._superSample ? (Math.ceil(this._lineHeightSuper / 2)) : this._lineHeightSuper;
-            this._offset = res.offset - 1;
-            this._xMargin = 1 + Math.ceil(this._lineHeightSuper / 15);    // Right now this empiric formula seems to work...
-            this._yMargin = this._xMargin;
+            this._offset = res.offset;
+            res = this.getFontHeight(font, "f");
+            this._baseLine = res.height + res.offset - this._offset;
 
-            var maxCharWidth = this._context.measureText("W").width;
+            var maxCharWidth = Math.max(this._context.measureText("W").width, this._context.measureText("_").width);
             this._spaceWidthSuper = this._context.measureText(" ").width;
             this._spaceWidth = this._superSample ? (this._spaceWidthSuper / 2) : this._spaceWidthSuper;
 
+            this._xMargin = Math.ceil(maxCharWidth / 32);
+            this._yMargin = this._xMargin;
+
             // This is an approximate size, but should always be able to fit at least the maxCharCount
-            var totalEstSurface = (this._lineHeightSuper + this._yMargin) * (maxCharWidth + this._xMargin) * maxCharCount;
+            var totalEstSurface = (Math.ceil(this._lineHeightSuper) + (this._yMargin*2)) * (Math.ceil(maxCharWidth) + (this._xMargin*2)) * maxCharCount;
             var edge = Math.sqrt(totalEstSurface);
             var textSize = Math.pow(2, Math.ceil(Math.log(edge) / Math.log(2)));
 
@@ -447,13 +458,13 @@
             this._context.clearRect(0, 0, textureSize.width, textureSize.height);
 
             // Create a canvas for the signed distance field mode, we only have to store one char, the purpose is to render a char scaled _sdfScale times
-            //  into this 2D context, then get the bitmap data, create the sdf char and push the result in the _context (which hold the whole Font Texture content)
+            //  into this 2D context, then get the bitmap data, create the SDF char and push the result in the _context (which hold the whole Font Texture content)
             // So you can see this context as an intermediate one, because it is.
             if (this._signedDistanceField) {
                 let sdfC = document.createElement("canvas");
                 let s = this._sdfScale;
-                sdfC.width = maxCharWidth * s;
-                sdfC.height = this._lineHeightSuper * s;
+                sdfC.width = (Math.ceil(maxCharWidth) + this._xMargin * 2) * s;
+                sdfC.height = (Math.ceil(this._lineHeightSuper) + this._yMargin * 2) * s;
                 let sdfCtx = sdfC.getContext("2d");
                 sdfCtx.scale(s, s);
                 sdfCtx.textBaseline = "top";
@@ -467,13 +478,50 @@
 
             this._currentFreePosition = Vector2.Zero();
 
-            // Add the basic ASCII based characters
+            // Add the basic ASCII based characters                                                               
             for (let i = 0x20; i < 0x7F; i++) {
                 var c = String.fromCharCode(i);
                 this.getChar(c);
             }
 
             this.update();
+
+            //this._saveToImage("");
+            
+        }
+
+        private _saveToImage(url: string) {
+            let base64Image = this._canvas.toDataURL("image/png");
+
+            //Creating a link if the browser have the download attribute on the a tag, to automatically start download generated image.
+            if (("download" in document.createElement("a"))) {
+                var a = window.document.createElement("a");
+                a.href = base64Image;
+                var date = new Date();
+                var stringDate = (date.getFullYear() + "-" + (date.getMonth() + 1)).slice(-2) +
+                    "-" +
+                    date.getDate() +
+                    "_" +
+                    date.getHours() +
+                    "-" +
+                    ('0' + date.getMinutes()).slice(-2);
+                a.setAttribute("download", "screenshot_" + stringDate + ".png");
+
+                window.document.body.appendChild(a);
+
+                a.addEventListener("click",
+                    () => {
+                        a.parentElement.removeChild(a);
+                    });
+                a.click();
+
+                //Or opening a new tab with the image if it is not possible to automatically start download.
+            } else {
+                var newWindow = window.open("");
+                var img = newWindow.document.createElement("img");
+                img.src = base64Image;
+                newWindow.document.body.appendChild(img);
+            }
         }
 
         /**
@@ -497,10 +545,10 @@
             var textureSize = this.getSize();
 
             // we reached the end of the current line?
-            let width = Math.round(measure.width);
+            let width = Math.ceil(measure.width);
             if (this._currentFreePosition.x + width + this._xMargin > textureSize.width) {
                 this._currentFreePosition.x = 0;
-                this._currentFreePosition.y += this._lineHeightSuper + this._yMargin;
+                this._currentFreePosition.y += Math.ceil(this._lineHeightSuper + this._yMargin*2);
 
                 // No more room?
                 if (this._currentFreePosition.y > textureSize.height) {
@@ -508,22 +556,68 @@
                 }
             }
 
-            // In sdf mode we render the character in an intermediate 2D context which scale the character this._sdfScale times (which is required to compute the sdf map accurately)
+            let curPosX = this._currentFreePosition.x + 0.5;
+            let curPosY = this._currentFreePosition.y + 0.5;
+            let curPosXMargin = curPosX + this._xMargin;
+            let curPosYMargin = curPosY + this._yMargin;
+
+            let drawDebug = (ctx: CanvasRenderingContext2D) => {
+                ctx.strokeStyle = "green";
+                ctx.beginPath();
+                ctx.rect(curPosXMargin, curPosYMargin, width, this._lineHeightSuper);
+                ctx.closePath();
+                ctx.stroke();
+
+                ctx.strokeStyle = "blue";
+                ctx.beginPath();
+                ctx.moveTo(curPosXMargin, curPosYMargin + Math.round(this._baseLine));
+                ctx.lineTo(curPosXMargin + width, curPosYMargin + Math.round(this._baseLine));
+                ctx.closePath();
+                ctx.stroke();
+            }
+
+            // In SDF mode we render the character in an intermediate 2D context which scale the character this._sdfScale times (which is required to compute the SDF map accurately)
             if (this._signedDistanceField) {
+                let s = this._sdfScale;
                 this._sdfContext.clearRect(0, 0, this._sdfCanvas.width, this._sdfCanvas.height);
-                this._sdfContext.fillText(char, 0, -this._offset);
-                let data = this._sdfContext.getImageData(0, 0, width*this._sdfScale, this._sdfCanvas.height);
 
+                // Coordinates are subject to the context's scale
+                this._sdfContext.fillText(char, this._xMargin + 0.5, this._yMargin + 0.5 - this._offset);
+
+                // Canvas Pixel Coordinates, no scale
+                let data = this._sdfContext.getImageData(0, 0, (width + (this._xMargin * 2)) * s, this._sdfCanvas.height);
                 let res = this._computeSDFChar(data);
-                this._context.putImageData(res, this._currentFreePosition.x, this._currentFreePosition.y);
+                this._context.putImageData(res, curPosX, curPosY);
+                if (this.debugMode) {
+                    drawDebug(this._context);
+                }
             } else {
+                if (this.debugMode) {
+                    drawDebug(this._context);
+                }
+
                 // Draw the character in the HTML canvas
-                this._context.fillText(char, this._currentFreePosition.x, this._currentFreePosition.y - this._offset);
+                this._context.fillText(char, curPosXMargin, curPosYMargin - this._offset);
+
+                // Premul Alpha manually
+                let id = this._context.getImageData(curPosXMargin, curPosYMargin, width, this._lineHeightSuper);
+                for (let i = 0; i < id.data.length; i += 4) {
+                    let v = id.data[i + 3];
+                    if (v > 0 && v < 255) {
+                        id.data[i + 0] = v;
+                        id.data[i + 1] = v;
+                        id.data[i + 2] = v;
+                        id.data[i + 3] = v;
+                    }
+
+                }
+                this._context.putImageData(id, curPosXMargin, curPosYMargin);
             }
 
             // Fill the CharInfo object
-            info.topLeftUV = new Vector2(this._currentFreePosition.x / textureSize.width, this._currentFreePosition.y / textureSize.height);
-            info.bottomRightUV = new Vector2((this._currentFreePosition.x + width) / textureSize.width, info.topLeftUV.y + ((this._lineHeightSuper + 2) / textureSize.height));
+            info.topLeftUV = new Vector2((curPosXMargin) / textureSize.width, (this._currentFreePosition.y + this._yMargin) / textureSize.height);
+            info.bottomRightUV = new Vector2((curPosXMargin + width) / textureSize.width, info.topLeftUV.y + ((this._lineHeightSuper + this._yMargin) / textureSize.height));
+            info.yOffset = info.xOffset = 0;
 
             if (this._signedDistanceField) {
                 let off = 1/textureSize.width;
@@ -532,13 +626,14 @@
             }
 
             info.charWidth = this._superSample ? (width/2) : width;
+            info.xAdvance = info.charWidth;
 
             // Add the info structure
             this._charInfos.add(char, info);
             this._curCharCount++;
 
             // Set the next position
-            this._currentFreePosition.x += width + this._xMargin;
+            this._currentFreePosition.x += Math.ceil(width + this._xMargin*2);
 
             return info;
         }
@@ -710,7 +805,7 @@
         }
 
         // More info here: https://videlais.com/2014/03/16/the-many-and-varied-problems-with-measuring-font-height-for-html5-canvas/
-        private getFontHeight(font: string): {height: number, offset: number} {
+        private getFontHeight(font: string, chars: string): {height: number, offset: number} {
             var fontDraw = document.createElement("canvas");
             fontDraw.width = 600;
             fontDraw.height = 600;
@@ -719,14 +814,16 @@
             ctx.textBaseline = 'top';
             ctx.fillStyle = 'white';
             ctx.font = font;
-            ctx.fillText('jH|', 0, 0);
+            ctx.fillText(chars, 0, 0);
             var pixels = ctx.getImageData(0, 0, fontDraw.width, fontDraw.height).data;
+
             var start = -1;
             var end = -1;
             for (var row = 0; row < fontDraw.height; row++) {
                 for (var column = 0; column < fontDraw.width; column++) {
                     var index = (row * fontDraw.width + column) * 4;
-                    if (pixels[index] === 0) {
+                    let pix = pixels[index];
+                    if (pix === 0) {
                         if (column === fontDraw.width - 1 && start !== -1) {
                             end = row;
                             row = fontDraw.height;
@@ -742,7 +839,7 @@
                     }
                 }
             }
-            return { height: (end - start)+1, offset: start-1}
+            return { height: (end - start)+1, offset: start}
         }
 
         public get canRescale(): boolean {
@@ -827,13 +924,15 @@
             return obj;
         }
 
-        private _buildCharInfo(initialLine: string, obj: any, textureSize: Size, invertY: boolean, chars: StringDictionary<CharInfo>) {
+        private _buildCharInfo(bfi: BitmapFontInfo, 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 xoffset = 0;
+            let yoffset = 0;
+            let xadvance = 0;
             let ci = new CharInfo();
             for (let key in obj) {
                 let value = obj[key];
@@ -854,15 +953,22 @@
                         height = value;
                         break;
                     case "xadvance":
-                        xadv = value;
+                        xadvance = value;
+                        break;
+                    case "xoffset":
+                        xoffset = value;
+                        break;
+                    case "yoffset":
+                        yoffset = value;
                         break;
                 }
             }
 
             if (x != null && y != null && width != null && height != null && char != null) {
-                if (xadv) {
-                    width = xadv;
-                }
+                ci.xAdvance = xadvance;
+                ci.xOffset = xoffset;
+                ci.yOffset = bfi.lineHeight -height - yoffset;
+
                 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));
@@ -895,6 +1001,7 @@
             //common
             var commonObj = this._parseStrToObj(fontStr.match(BMFontLoaderTxt.COMMON_EXP)[0]);
             bfi.lineHeight = commonObj["lineHeight"];
+            bfi.baseLine = commonObj["base"];
             bfi.textureSize = new Size(commonObj["scaleW"], commonObj["scaleH"]);
 
             var maxTextureSize = scene.getEngine()._gl.getParameter(0xd33);
@@ -918,7 +1025,7 @@
                         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);
+                            this._buildCharInfo(bfi, charLines[i], charObj, bfi.textureSize, invertY, bfi.charDic);
                         }
 
                         //kerning

+ 6 - 48
canvas2D/src/Engine/babylon.group2d.ts

@@ -113,7 +113,7 @@
             paddingLeft             ?: number | string,
             paddingRight            ?: number | string,
             paddingBottom           ?: number | string,
-            padding                 ?: string,
+            padding                 ?: number | string,
 
         }) {
             if (settings == null) {
@@ -249,7 +249,7 @@
 
         @instanceLevelProperty(Prim2DBase.PRIM2DBASE_PROPCOUNT + 1, pi => Group2D.sizeProperty = pi, false, true)
         public get size(): Size {
-            return this._size;
+            return this.internalGetSize();
         }
 
         /**
@@ -264,49 +264,6 @@
             return this._viewportSize;
         }
 
-        @instanceLevelProperty(Prim2DBase.PRIM2DBASE_PROPCOUNT + 2, pi => Group2D.actualSizeProperty = pi)
-        /**
-         * Get the actual size of the group, if the size property is not null, this value will be the same, but if size is null, actualSize will return the size computed from the group's bounding content.
-         */
-        public get actualSize(): Size {
-            // The computed size will be floor on both width and height
-            let actualSize: Size;
-
-            // Return the actualSize if set
-            if (this._actualSize) {
-                return this._actualSize;
-            }
-
-            // Return the size if set by the user
-            if (this._size) {
-                actualSize = new Size(Math.ceil(this._size.width), Math.ceil(this._size.height));
-            }
-
-            // Otherwise the size is computed based on the boundingInfo of the layout (or bounding info) content
-            else {
-                let m = this.layoutBoundingInfo.max();
-                actualSize = new Size(Math.ceil(m.x), Math.ceil(m.y));
-            }
-
-            // Compare the size with the one we previously had, if it differs we set the property dirty and trigger a GroupChanged to synchronize a displaySprite (if any)
-            if (!actualSize.equals(this._actualSize)) {
-                this.onPrimitivePropertyDirty(Group2D.actualSizeProperty.flagId);
-                this._actualSize = actualSize;
-                this.handleGroupChanged(Group2D.actualSizeProperty);
-            }
-
-            return actualSize;
-        }
-
-        public set actualSize(value: Size) {
-            if (!this._actualSize) {
-                this._actualSize = value.clone();
-            } else {
-                this._actualSize.copyFrom(value);
-            }
-        }
-
-
         /**
          * Get/set the Cache Behavior, used in case the Canvas Cache Strategy is set to CACHESTRATEGY_ALLGROUPS. Can be either GROUPCACHEBEHAVIOR_CACHEINPARENTGROUP, GROUPCACHEBEHAVIOR_DONTCACHEOVERRIDE or GROUPCACHEBEHAVIOR_FOLLOWCACHESTRATEGY. See their documentation for more information.
          * GROUPCACHEBEHAVIOR_NORESIZEONSCALE can also be set if you set it at creation time.
@@ -398,8 +355,9 @@
 
             let s = this.actualSize;
             let a = this.actualScale;
-            let sw = Math.ceil(s.width * a.x);
-            let sh = Math.ceil(s.height * a.y);
+            let hwsl = 1/this.owner.engine.getHardwareScalingLevel();
+            let sw = Math.ceil(s.width * a.x * hwsl);
+            let sh = Math.ceil(s.height * a.y * hwsl);
 
             // The dimension must be overridden when using the designSize feature, the ratio is maintain to compute a uniform scale, which is mandatory but if the designSize's ratio is different from the rendering surface's ratio, content will be clipped in some cases.
             // So we set the width/height to the rendering's one because that's what we want for the viewport!
@@ -413,7 +371,7 @@
             if (!this._isCachedGroup) {
                 // Compute the WebGL viewport's location/size
                 let t = this._globalTransform.getTranslation();
-                let rs = this.owner._renderingSize;
+                let rs = this.owner._renderingSize.multiplyByFloats(hwsl, hwsl);
                 sh = Math.min(sh, rs.height - t.y);
                 sw = Math.min(sw, rs.width - t.x);
                 let x = t.x;

+ 1 - 1
canvas2D/src/Engine/babylon.lines2d.ts

@@ -409,7 +409,7 @@
             paddingLeft           ?: number | string,
             paddingRight          ?: number | string,
             paddingBottom         ?: number | string,
-            padding               ?: string,
+            padding               ?: number | string,
         }) {
 
             if (!settings) {

文件差異過大導致無法顯示
+ 689 - 286
canvas2D/src/Engine/babylon.prim2dBase.ts


+ 7 - 22
canvas2D/src/Engine/babylon.rectangle2d.ts

@@ -170,25 +170,6 @@
         public static notRoundedProperty: Prim2DPropInfo;
         public static roundRadiusProperty: Prim2DPropInfo;
 
-        @instanceLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 1, pi => Rectangle2D.actualSizeProperty = pi, false, true)
-        /**
-         * Get/set the rectangle size (width/height)
-         */
-        public get actualSize(): Size {
-            if (this._actualSize) {
-                return this._actualSize;
-            }
-            return this.size;
-        }
-
-        public set actualSize(value: Size) {
-            if (!this._actualSize) {
-                this._actualSize = value.clone();
-            } else {
-                this._actualSize.copyFrom(value);
-            }
-        }
-
         @modelLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 2, pi => Rectangle2D.notRoundedProperty = pi)
         /**
          * Get if the rectangle is notRound (returns true) or rounded (returns false).
@@ -377,7 +358,7 @@
             paddingLeft           ?: number | string,
             paddingRight          ?: number | string,
             paddingBottom         ?: number | string,
-            padding               ?: string,
+            padding               ?: number | string,
         }) {
 
             // Avoid checking every time if the object exists
@@ -577,15 +558,19 @@
             }
         }
 
-        protected _getActualSizeFromContentToRef(primSize: Size, newPrimSize: Size) {
+        protected _getActualSizeFromContentToRef(primSize: Size, paddingOffset: Vector4, newPrimSize: Size) {
             // Fall back to default implementation if there's no round Radius
             if (this._notRounded) {
-                super._getActualSizeFromContentToRef(primSize, newPrimSize);
+                super._getActualSizeFromContentToRef(primSize, paddingOffset, newPrimSize);
             } else {
                 let rr = Math.round((this.roundRadius - (this.roundRadius / Math.sqrt(2))) * 1.3);
                 newPrimSize.copyFrom(primSize);
                 newPrimSize.width  += rr * 2;
                 newPrimSize.height += rr * 2;
+                paddingOffset.x += rr;
+                paddingOffset.y += rr;
+                paddingOffset.z += rr;
+                paddingOffset.w += rr;
             }
         }
 

+ 14 - 20
canvas2D/src/Engine/babylon.renderablePrim2d.ts

@@ -931,7 +931,7 @@
         private static _s = Vector3.Zero();
         private static _r = Quaternion.Identity();
         private static _t = Vector3.Zero();
-        private static _uV3 = new Vector3(1, 1, 1);
+        private static _iV3 = new Vector3(1, 1, 1); // Must stay identity vector3
         /**
          * Update the instanceDataBase level properties of a part
          * @param part the part to update
@@ -939,12 +939,22 @@
          */
         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.
+            let scl = RenderablePrim2D._s;
+            let rot = RenderablePrim2D._r;
+            let trn = RenderablePrim2D._t;
+            t.decompose(scl, rot, trn);
+            let pas = this.actualScale;
+            scl.x = pas.x;
+            scl.y = pas.y;
+            scl.z = 1;
+            t = Matrix.Compose(this.applyActualScaleOnTransform() ? scl : RenderablePrim2D._iV3, rot, trn);
+
             let size = (<Size>this.renderGroup.viewportSize);
             let zBias = this.actualZOffset;
 
             let offX = 0;
             let offY = 0;
+
             // If there's an offset, apply the global transformation matrix on it to get a global offset
             if (positionOffset) {
                 offX = positionOffset.x * t.m[0] + positionOffset.y * t.m[4];
@@ -960,25 +970,9 @@
             let w = size.width;
             let h = size.height;
             let invZBias = 1 / zBias;
-            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]);
-            }
-
-            tx.x /= w;
-            tx.y /= w;
+            let tx = new Vector4(t.m[0] * 2 / w, t.m[4] * 2 / w, 0, ((t.m[12] + offX) * 2 / w) - 1);
+            let ty = new Vector4(t.m[1] * 2 / h, t.m[5] * 2 / h, 0, ((t.m[13] + offY) * 2 / h) - 1);
 
-            ty.x /= h;
-            ty.y /= h;
 
             part.transformX = tx;
             part.transformY = ty;

+ 6 - 1
canvas2D/src/Engine/babylon.smartPropertyPrim.ts

@@ -1112,7 +1112,9 @@
                     curprim._setFlags(SmartPropertyPrim.flagBoundingInfoDirty);
                     if (curprim.isSizeAuto) {
                         curprim.onPrimitivePropertyDirty(Prim2DBase.sizeProperty.flagId);
-                        curprim._setFlags(SmartPropertyPrim.flagPositioningDirty);
+                        if (curprim._isFlagSet(SmartPropertyPrim.flagUsePositioning)) {
+                            curprim._setFlags(SmartPropertyPrim.flagPositioningDirty);
+                        }
                     }
 
                     if (curprim instanceof Group2D) {
@@ -1305,6 +1307,9 @@
         public static flagLayoutBoundingInfoDirty = 0x0200000;    // set if the layout bounding info is dirty
         public static flagCollisionActor          = 0x0400000;    // set if the primitive is part of the collision engine
         public static flagModelUpdate             = 0x0800000;    // set if the primitive's model data is to update
+        public static flagLocalTransformDirty     = 0x1000000;    // set if the local transformation matrix must be recomputed
+        public static flagUsePositioning          = 0x2000000;    // set if the primitive rely on the positioning engine (padding or margin is used)
+        public static flagComputingPositioning    = 0x4000000;    // set if the positioning engine is computing the primitive, used to avoid re entrance
 
         private   _uid                : string;
         private   _flags              : number;

+ 6 - 23
canvas2D/src/Engine/babylon.sprite2d.ts

@@ -145,24 +145,6 @@
             this._updateSpriteScaleFactor();
         }
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 3, pi => Sprite2D.actualSizeProperty = pi, false, true)
-        /**
-         * Get/set the actual size of the sprite to display
-         */
-        public get actualSize(): Size {
-            if (this._actualSize) {
-                return this._actualSize;
-            }
-            return this.size;
-        }
-
-        public set actualSize(value: Size) {
-            if (!this._actualSize) {
-                this._actualSize = value.clone();
-            } else {
-                this._actualSize.copyFrom(value);
-            }
-        }
 
         @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 4, pi => Sprite2D.spriteSizeProperty = pi, false, true)
         /**
@@ -363,7 +345,7 @@
             paddingLeft           ?: number | string,
             paddingRight          ?: number | string,
             paddingBottom         ?: number | string,
-            padding               ?: string,
+            padding               ?: number | string,
         }) {
 
             if (!settings) {
@@ -373,8 +355,9 @@
             super(settings);
 
             this.texture = texture;
-            this.texture.wrapU = Texture.CLAMP_ADDRESSMODE;
-            this.texture.wrapV = Texture.CLAMP_ADDRESSMODE;
+            // This is removed to let the user the possibility to setup the addressing mode he wants
+            //this.texture.wrapU = Texture.CLAMP_ADDRESSMODE;
+            //this.texture.wrapV = Texture.CLAMP_ADDRESSMODE;
             this._useSize = false;
             this._spriteSize = (settings.spriteSize!=null) ? settings.spriteSize.clone() : null;
             this._spriteLocation = (settings.spriteLocation!=null) ? settings.spriteLocation.clone() : new Vector2(0, 0);
@@ -556,8 +539,8 @@
             if (s == null || sS == null) {
                 return;
             }
-            this.scaleX = s.width / sS.width;
-            this.scaleY = s.height / sS.height;
+            this._postScale.x = s.width / sS.width;
+            this._postScale.y = s.height / sS.height;
         }
 
         private _texture: Texture;

文件差異過大導致無法顯示
+ 75 - 21
canvas2D/src/Engine/babylon.text2d.ts


+ 1 - 20
canvas2D/src/Engine/babylon.wireFrame2d.ts

@@ -233,25 +233,6 @@
             this.internalSetSize(value);
         }
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 2, pi => WireFrame2D.actualSizeProperty = pi, false, true)
-        /**
-         * Get/set the actual size of the sprite to display
-         */
-        public get actualSize(): Size {
-            if (this._actualSize) {
-                return this._actualSize;
-            }
-            return this.size;
-        }
-
-        public set actualSize(value: Size) {
-            if (!this._actualSize) {
-                this._actualSize.clone();
-            } else {
-                this._actualSize.copyFrom(value);
-            }
-        }
-
         protected updateLevelBoundingInfo(): boolean {
             let v = this._computeMinMaxTrans();
             BoundingInfo2D.CreateFromMinMaxToRef(v.x, v.z, v.y, v.w, this._levelBoundingInfo);
@@ -337,7 +318,7 @@
             paddingLeft           ?: number | string,
             paddingRight          ?: number | string,
             paddingBottom         ?: number | string,
-            padding               ?: string,
+            padding               ?: number | string,
         }) {
 
             if (!settings) {

+ 582 - 0
canvas2D/src/Tools/babylon.math2D.ts

@@ -1,5 +1,545 @@
 module BABYLON {
 
+    /**
+     * This class stores the data to make 2D transformation using a Translation (tX, tY), a Scale (sX, sY) and a rotation around the Z axis (rZ).
+     * You can multiply two Transform2D object to produce the result of their concatenation.
+     * You can transform a given Point (a Vector2D instance) with a Transform2D object or with the Invert of the Transform2D object.
+     * There no need to compute/store the Invert of a Transform2D as the invertTranform methods are almost as fast as the transform ones.
+     * This class is as light as it could be and the transformation operations are pretty optimal.
+     */
+    export class Transform2D {
+        /**
+         * A 2D Vector representing the translation to the origin
+         */
+        public translation: Vector2;
+
+        /**
+         * A number (in radian) representing the rotation around the Z axis at the origin
+         */
+        public rotation: number;
+
+        /**
+         * A 2D Vector representing the scale to apply at the origin
+         */
+        public scale: Vector2;
+
+        constructor() {
+            this.translation = Vector2.Zero();
+            this.rotation = 0;
+            this.scale = new Vector2(1, 1);
+        }
+
+        /**
+         * Set the Transform2D object with the given values
+         * @param translation The translation to set
+         * @param rotation The rotation (in radian) to set
+         * @param scale The scale to set
+         */
+        public set(translation: Vector2, rotation: number, scale: Vector2) {
+            this.translation.copyFrom(translation);
+            this.rotation = rotation;
+            this.scale.copyFrom(scale);
+        }
+
+        /**
+         * Set the Transform2D object from float values
+         * @param transX The translation on X axis, nothing is set if not specified
+         * @param transY The translation on Y axis, nothing is set if not specified
+         * @param rotation The rotation in radian, nothing is set if not specified
+         * @param scaleX The scale along the X axis, nothing is set if not specified
+         * @param scaleY The scale along the Y axis, nothing is set if not specified
+         */
+        public setFromFloats(transX?: number, transY?: number, rotation?: number, scaleX?: number, scaleY?: number) {
+            if (transX) {
+                this.translation.x = transX;
+            }
+
+            if (transY) {
+                this.translation.y = transY;
+            }
+
+            if (rotation) {
+                this.rotation = rotation;
+            }
+
+            if (scaleX) {
+                this.scale.x = scaleX;
+            }
+
+            if (scaleY) {
+                this.scale.y = scaleY;
+            }
+        }
+
+        /**
+         * Return a copy of the object
+         */
+        public clone(): Transform2D {
+            let res = new Transform2D();
+            res.translation.copyFrom(this.translation);
+            res.rotation = this.rotation;
+            res.scale.copyFrom(this.scale);
+
+            return res;
+        }
+
+        /**
+         * Convert a given degree angle into its radian equivalent
+         * @param angleDegree the number to convert
+         */
+        public static ToRadian(angleDegree: number): number {
+            return angleDegree * Math.PI * 2 / 360;
+        }
+
+        /**
+         * Create a new instance and returns it
+         * @param translation The translation to store, default is (0,0)
+         * @param rotation The rotation to store, default is 0
+         * @param scale The scale to store, default is (1,1)
+         */
+        public static Make(translation?: Vector2, rotation?: number, scale?: Vector2): Transform2D {
+            let res = new Transform2D();
+            if (translation) {
+                res.translation.copyFrom(translation);
+            }
+            if (rotation) {
+                res.rotation = rotation;
+            }
+            if (scale) {
+                res.scale.copyFrom(scale);
+            }
+
+            return res;
+        }
+
+        /**
+         * Set the given Transform2D object with the given values
+         * @param translation The translation to store, default is (0,0)
+         * @param rotation The rotation to store, default is 0
+         * @param scale The scale to store, default is (1,1)
+         */
+        public static MakeToRef(res: Transform2D, translation?: Vector2, rotation?: number, scale?: Vector2) {
+            if (translation) {
+                res.translation.copyFrom(translation);
+            } else {
+                res.translation.copyFromFloats(0, 0);
+            }
+            if (rotation) {
+                res.rotation = rotation;
+            } else {
+                res.rotation = 0;
+            }
+            if (scale) {
+                res.scale.copyFrom(scale);
+            } else {
+                res.scale.copyFromFloats(1, 1);
+            }
+        }
+
+        /**
+         * Create a Transform2D object from float values
+         * @param transX The translation on X axis, 0 per default
+         * @param transY The translation on Y axis, 0 per default
+         * @param rotation The rotation in radian, 0 per default
+         * @param scaleX The scale along the X axis, 1 per default
+         * @param scaleY The scale along the Y axis, 1 per default
+         */
+        public static MakeFromFloats(transX?: number, transY?: number, rotation?: number, scaleX?: number, scaleY?: number): Transform2D {
+            let res = new Transform2D();
+
+            if (transX) {
+                res.translation.x = transX;
+            }
+
+            if (transY) {
+                res.translation.y = transY;
+            }
+
+            if (rotation) {
+                res.rotation = rotation;
+            }
+
+            if (scaleX) {
+                res.scale.x = scaleX;
+            }
+
+            if (scaleY) {
+                res.scale.y = scaleY;
+            }
+
+            return res;
+        }
+
+        /**
+         * Set the given Transform2D object with the given float values
+         * @param transX The translation on X axis, 0 per default
+         * @param transY The translation on Y axis, 0 per default
+         * @param rotation The rotation in radian, 0 per default
+         * @param scaleX The scale along the X axis, 1 per default
+         * @param scaleY The scale along the Y axis, 1 per default
+         */
+        public static MakeFromFloatsToRef(res: Transform2D, transX?: number, transY?: number, rotation?: number, scaleX?: number, scaleY?: number) {
+            res.translation.x = (transX!=null)   ? transX   : 0;
+            res.translation.y = (transY!=null)   ? transY   : 0;
+            res.rotation      = (rotation!=null) ? rotation : 0;
+            res.scale.x       = (scaleX!=null)   ? scaleX   : 1;
+            res.scale.y       = (scaleY!=null)   ? scaleY   : 1;
+        }
+
+        /**
+         * Create a Transform2D containing only Zeroed values
+         */
+        public static Zero(): Transform2D {
+            let res = new Transform2D();
+            res.scale.copyFromFloats(0, 0);
+            return res;
+        }
+
+        /**
+         * Copy the value of the other object into 'this'
+         * @param other The other object to copy values from
+         */
+        public copyFrom(other: Transform2D) {
+            this.translation.copyFrom(other.translation);
+            this.rotation = other.rotation;
+            this.scale.copyFrom(other.scale);
+        }
+
+        public toMatrix2D(): Matrix2D {
+            let res = new Matrix2D();
+            this.toMatrix2DToRef(res);
+            return res;
+        }
+
+        public toMatrix2DToRef(res: Matrix2D) {
+            let tx = this.translation.x;
+            let ty = this.translation.y;
+            let r = this.rotation;
+            let cosr = Math.cos(r);
+            let sinr = Math.sin(r);
+            let sx = this.scale.x;
+            let sy = this.scale.y;
+
+            res.m[0] = cosr * sx;   res.m[1] = sinr * sy;
+            res.m[2] = -sinr* sx;   res.m[3] = cosr * sy;
+            res.m[4] = tx;          res.m[5] = ty;
+        }
+
+        /**
+         * In place transformation from a parent matrix.
+         * @param parent transform object. "this" will be the result of parent * this
+         */
+        public multiplyToThis(parent: Transform2D) {
+            this.multiplyToRef(parent, this);
+        }
+
+        /**
+         * Transform this object with a parent and return the result. Result = parent * this
+         * @param parent The parent transformation
+         */
+        public multiply(parent: Transform2D): Transform2D {
+            let res = new Transform2D();
+            this.multiplyToRef(parent, res);
+            return res;
+        }
+
+        /**
+         * Transform a point and store the result in the very same object
+         * @param p Transform this point and change the values with the transformed ones
+         */
+        public transformPointInPlace(p: Vector2) {
+            this.transformPointToRef(p, p);
+        }
+
+        /**
+         * Transform a point and store the result into a reference object
+         * @param p The point to transform
+         * @param res Will contain the new transformed coordinates. Can be the object of 'p'.
+         */
+        public transformPointToRef(p: Vector2, res: Vector2) {
+            this.transformFloatsToRef(p.x, p.y, res);
+        }
+
+        /**
+         * Transform this object with a parent and store the result in reference object
+         * @param parent The parent transformation
+         * @param result Will contain parent * this. Can be the object of either parent or 'this'
+         */
+        public multiplyToRef(parent: Transform2D, result: Transform2D) {
+            if (!parent || !result) {
+                throw new Error("Valid parent and result objects must be specified");
+            }
+            let tx = this.translation.x;
+            let ty = this.translation.y;
+            let ptx = parent.translation.x;
+            let pty = parent.translation.y;
+            let pr = parent.rotation;
+            let psx = parent.scale.x;
+            let psy = parent.scale.y;
+            let cosr = Math.cos(pr);
+            let sinr = Math.sin(pr);
+            result.translation.x = (((tx * cosr) - (ty * sinr)) * psx) + ptx;
+            result.translation.y = (((tx * sinr) + (ty * cosr)) * psy) + pty;
+            this.scale.multiplyToRef(parent.scale, result.scale);
+            result.rotation = this.rotation;
+        }
+
+        /**
+         * Transform the given coordinates and store the result in a Vector2 object
+         * @param x The X coordinate to transform
+         * @param y The Y coordinate to transform
+         * @param res The Vector2 object that will contain the result of the transformation
+         */
+        public transformFloatsToRef(x: number, y: number, res: Vector2) {
+            let tx = this.translation.x;
+            let ty = this.translation.y;
+            let pr = this.rotation;
+            let sx = this.scale.x;
+            let sy = this.scale.y;
+            let cosr = Math.cos(pr);
+            let sinr = Math.sin(pr);
+            res.x = (((x * cosr) - (y * sinr)) * sx) + tx;
+            res.y = (((x * sinr) + (y * cosr)) * sy) + ty;
+        }
+
+        /**
+         * Invert transform the given coordinates and store the result in a reference object. res = invert(this) * (x,y)
+         * @param p Transform this point and change the values with the transformed ones
+         * @param res Will contain the result of the invert transformation.
+         */
+        public invertTransformFloatsToRef(x: number, y: number, res: Vector2) {
+            let px = x - this.translation.x;
+            let py = y - this.translation.y;
+
+            let pr = -this.rotation;
+            let sx = this.scale.x;
+            let sy = this.scale.y;
+            let psx = (sx===1) ? 1 : (1/sx);
+            let psy = (sy===1) ? 1 : (1/sy);
+            let cosr = Math.cos(pr);
+            let sinr = Math.sin(pr);
+            res.x = (((px * cosr) - (py * sinr)) * psx);
+            res.y = (((px * sinr) + (py * cosr)) * psy);
+        }
+
+        /**
+         * Transform a point and return the result
+         * @param p the point to transform
+         */
+        public transformPoint(p: Vector2): Vector2 {
+            let res = Vector2.Zero();
+            this.transformPointToRef(p, res);
+            return res;
+        }
+
+        /**
+         * Transform the given coordinates and return the result in a Vector2 object
+         * @param x The X coordinate to transform
+         * @param y The Y coordinate to transform
+         */
+        public transformFloats(x: number, y: number): Vector2 {
+            let res = Vector2.Zero();
+            this.transformFloatsToRef(x, y, res);
+            return res;
+        }
+
+        /**
+         * Invert transform a given point and store the result in the very same object. p = invert(this) * p
+         * @param p Transform this point and change the values with the transformed ones
+         */
+        public invertTransformPointInPlace(p: Vector2) {
+            this.invertTransformPointToRef(p, p);
+        }
+
+        /**
+         * Invert transform a given point and store the result in a reference object. res = invert(this) * p
+         * @param p Transform this point and change the values with the transformed ones
+         * @param res Will contain the result of the invert transformation. 'res' can be the same object as 'p'
+         */
+        public invertTransformPointToRef(p: Vector2, res: Vector2) {
+            this.invertTransformFloatsToRef(p.x, p.y, res);
+        }
+
+        /**
+         * Invert transform a given point and return the result. return = invert(this) * p
+         * @param p The Point to transform
+         */
+        public invertTransformPoint(p: Vector2): Vector2 {
+            let res = Vector2.Zero();
+            this.invertTransformPointToRef(p, res);
+            return res;
+        }
+
+        /**
+         * Invert transform the given coordinates and return the result. return = invert(this) * (x,y)
+         * @param x The X coordinate to transform
+         * @param y The Y coordinate to transform
+         */
+        public invertTransformFloats(x: number, y: number): Vector2 {
+            let res = Vector2.Zero();
+            this.invertTransformFloatsToRef(x, y, res);
+            return res;
+        }
+    }
+
+    /**
+     * A class storing a Matrix for 2D transformations
+     * The stored matrix is a 2*3 Matrix
+     * I   [0,1]   [mX, mY]   R   [ CosZ, SinZ]  T    [ 0,  0]  S   [Sx,  0]
+     * D = [2,3] = [nX, nY]   O = [-SinZ, CosZ]  R =  [ 0,  0]  C = [ 0, Sy]
+     * X   [4,5]   [tX, tY]   T   [  0  ,  0  ]  N    [Tx, Ty]  L   [ 0,  0]
+     *
+     * IDX = index, zero based. ROT = Z axis Rotation. TRN = Translation. SCL = Scale.
+     */
+    export class Matrix2D {
+
+        public static Identity(): Matrix2D {
+            let res = new Matrix2D();
+            Matrix2D.IdentityToRef(res);
+            return res;
+        }
+
+        public static IdentityToRef(res: Matrix2D) {
+            res.m[1] = res.m[2] = res.m[4] = res.m[5] = 0;
+            res.m[0] = res.m[3] = 1;           
+        }
+
+        public copyFrom(other: Matrix2D) {
+            for (let i = 0; i < 6; i++) {
+                this.m[i] = other.m[i];
+            }
+        }
+
+        public determinant(): number {
+            return (this.m[0] * this.m[3]) - (this.m[1] * this.m[2]);
+        }
+
+        public invertToThis() {
+            this.invertToRef(this);
+        }
+
+        public invert(): Matrix2D {
+            let res = new Matrix2D();
+            this.invertToRef(res);
+            return res;
+        }
+
+        public invertToRef(res: Matrix2D) {
+            let a00 = this.m[0], a01 = this.m[1],
+                a10 = this.m[2], a11 = this.m[3],
+                a20 = this.m[4], a21 = this.m[5];
+
+            let det21 = a21 * a10 - a11 * a20;
+
+            let det = (a00 * a11) - (a01 * a10);
+            if (det < (Epsilon*Epsilon)) {
+                throw new Error("Can't invert matrix, near null determinant");
+            }
+
+            det = 1 / det;
+
+            res.m[0] = a11 * det;
+            res.m[1] = -a01 * det;
+            res.m[2] = -a10 * det;
+            res.m[3] = a00 * det;
+            res.m[4] = det21 * det;
+            res.m[5] = (-a21 * a00 + a01 * a20) * det;
+        }
+
+        public multiplyToThis(other: Matrix2D) {
+            this.multiplyToRef(other, this);
+        }
+
+        public multiply(other: Matrix2D): Matrix2D {
+            let res = new Matrix2D();
+            this.multiplyToRef(other, res);
+            return res;
+        }
+
+        public multiplyToRef(other: Matrix2D, result: Matrix2D) {
+            var tm0 = this.m[0];
+            var tm1 = this.m[1];
+            //var tm2 = this.m[2];
+            //var tm3 = this.m[3];
+            var tm4 = this.m[2];
+            var tm5 = this.m[3];
+            //var tm6 = this.m[6];
+            //var tm7 = this.m[7];
+            var tm8 = this.m[4];
+            var tm9 = this.m[5];
+            //var tm10 = this.m[10];
+            //var tm11 = this.m[11];
+            //var tm12 = this.m[12];
+            //var tm13 = this.m[13];
+            //var tm14 = this.m[14];
+            //var tm15 = this.m[15];
+
+            var om0 = other.m[0];
+            var om1 = other.m[1];
+            //var om2 = other.m[2];
+            //var om3 = other.m[3];
+            var om4 = other.m[2];
+            var om5 = other.m[3];
+            //var om6 = other.m[6];
+            //var om7 = other.m[7];
+            var om8 = other.m[4];
+            var om9 = other.m[5];
+            //var om10 = other.m[10];
+            //var om11 = other.m[11];
+            //var om12 = other.m[12];
+            //var om13 = other.m[13];
+            //var om14 = other.m[14];
+            //var om15 = other.m[15];
+
+            result.m[0] = tm0 * om0 + tm1 * om4;
+            result.m[1] = tm0 * om1 + tm1 * om5;
+            //result.m[2] = tm0 * om2 + tm1 * om6 + tm2 * om10 + tm3 * om14;
+            //result.m[3] = tm0 * om3 + tm1 * om7 + tm2 * om11 + tm3 * om15;
+
+            result.m[2] = tm4 * om0 + tm5 * om4;
+            result.m[3] = tm4 * om1 + tm5 * om5;
+            //result.m[6] = tm4 * om2 + tm5 * om6 + tm6 * om10 + tm7 * om14;
+            //result.m[7] = tm4 * om3 + tm5 * om7 + tm6 * om11 + tm7 * om15;
+
+            result.m[4] = tm8 * om0 + tm9 * om4 + om8;
+            result.m[5] = tm8 * om1 + tm9 * om5 + om9;
+            //result.m[10] = tm8 * om2 + tm9 * om6 + tm10 * om10 + tm11 * om14;
+            //result.m[11] = tm8 * om3 + tm9 * om7 + tm10 * om11 + tm11 * om15;
+
+            //result.m[12] = tm12 * om0 + tm13 * om4 + tm14 * om8 + tm15 * om12;
+            //result.m[13] = tm12 * om1 + tm13 * om5 + tm14 * om9 + tm15 * om13;
+            //result.m[14] = tm12 * om2 + tm13 * om6 + tm14 * om10 + tm15 * om14;
+            //result.m[15] = tm12 * om3 + tm13 * om7 + tm14 * om11 + tm15 * om15;
+        }
+
+        public transformFloats(x: number, y: number): Vector2 {
+            let res = Vector2.Zero();
+            this.transformFloatsToRef(x, y, res);
+            return res;
+        }
+
+        public transformFloatsToRef(x: number, y: number, r: Vector2) {
+            r.x = x * this.m[0] + y * this.m[2] + this.m[4];
+            r.y = x * this.m[1] + y * this.m[3] + this.m[5];
+        }
+
+        public transformPoint(p: Vector2): Vector2 {
+            let res = Vector2.Zero();
+            this.transformFloatsToRef(p.x, p.y, res);
+            return res;
+        }
+
+        public transformPointToRef(p: Vector2, r: Vector2) {
+            this.transformFloatsToRef(p.x, p.y, r);
+        }
+
+        public m = new Float32Array(6);
+    }
+
+    /**
+     * Stores information about a 2D Triangle.
+     * This class stores the 3 vertices but also the center and radius of the triangle
+     */
     export class Tri2DInfo {
         /**
          * Construct an instance of Tri2DInfo, you can either pass null to a, b and c and the instance will be allocated "clear", or give actual triangle info and the center/radius will be computed
@@ -64,12 +604,22 @@
         }
     }
 
+    /**
+     * Stores an array of 2D Triangles.
+     * Internally the data is stored as a Float32Array to minimize the memory footprint.
+     * This can use the Tri2DInfo class as proxy for storing/retrieving data.
+     * The array can't grow, it's fixed size.
+     */
     export class Tri2DArray {
         constructor(count: number) {
             this._count = count;
             this._array = new Float32Array(9 * count);
         }
 
+        /**
+         * Clear the content and allocate a new array to store the given count of triangles
+         * @param count The new count of triangles to store
+         */
         public clear(count: number) {
             if (this._count === count) {
                 return;
@@ -79,6 +629,13 @@
             this._array = new Float32Array(9 * count);
         }
 
+        /**
+         * Store a given triangle at the given index
+         * @param index the 0 based index to store the triangle in the array
+         * @param a the A vertex of the triangle
+         * @param b the B vertex of the triangle
+         * @param c the C vertex of the triangle
+         */
         public storeTriangle(index: number, a: Vector2, b: Vector2, c: Vector2) {
             let center = new Vector2((a.x + b.x + c.x) / 3, (a.y + b.y + c.y) / 3);
 
@@ -123,6 +680,12 @@
             tri2dInfo.radius   = this._array[offset + 8];
         }
 
+        /**
+         * Transform the given triangle and store its result in the array
+         * @param index The index to store the result to
+         * @param tri2dInfo The triangle to transform
+         * @param transform The transformation matrix
+         */
         public transformAndStoreToTri2DInfo(index: number, tri2dInfo: Tri2DInfo, transform: Matrix) {
             if (index >= this._count) {
                 throw new Error(`Can't fetch the triangle at index ${index}, max index is ${this._count - 1}`);
@@ -139,10 +702,19 @@
             tri2dInfo.transformInPlace(transform);
         }
 
+        /**
+         * Get the element count that can be stored in this array
+         * @returns {} 
+         */
         public get count(): number {
             return this._count;
         }
 
+        /**
+         * Check if a given point intersects with at least one of the triangles stored in the array.
+         * If true is returned the point is intersecting with at least one triangle, false if it doesn't intersect with any of them
+         * @param p The point to check
+         */
         public doesContain(p: Vector2): boolean {
             Tri2DArray._checkInitStatics();
             let a = Tri2DArray.tempT[0];
@@ -156,6 +728,13 @@
             return false;
         }
 
+        /**
+         * Make a intersection test between two sets of triangles. The triangles of setB will be transformed to the frame of reference of the setA using the given bToATransform matrix.
+         * If true is returned at least one triangle intersects with another of the other set, otherwise false is returned.
+         * @param setA The first set of triangles
+         * @param setB The second set of triangles
+         * @param bToATransform The transformation matrix to transform the setB triangles into the frame of reference of the setA
+         */
         public static doesIntersect(setA: Tri2DArray, setB: Tri2DArray, bToATransform: Matrix): boolean {
             Tri2DArray._checkInitStatics();
 
@@ -209,6 +788,9 @@
         private static tempT: Tri2DInfo[] = null;
     }
 
+    /**
+     * Some 2D Math helpers functions
+     */
     class Math2D {
 
         static Dot(a: Vector2, b: Vector2): number {

+ 7 - 0
canvas2D/src/shaders/text2d.fragment.fx

@@ -22,7 +22,14 @@ void main(void) {
 	gl_FragColor = vec4(vColor.xyz*dist, vColor.a);
 #else
 	vec4 color = texture2D(diffuseSampler, vUV);
+	if (color.a == 0.0) {
+		discard;
+	}
+#ifdef FontTexture
+	gl_FragColor = vec4(color.xxxx)*vColor;
+#else
 	gl_FragColor = color*vColor;
 #endif
+#endif
 
 }

+ 33 - 0
contributing.md

@@ -0,0 +1,33 @@
+# Contributing to Babylon.js
+
+The foundation of **Babylon.js** is simplicity. 
+
+A developer should be able to quickly and easily learn to use the API. 
+
+Simplicity and a low barrier to entry are must-have features of every API. If you have any second thoughts about the complexity of a design, it is almost always much better to cut the feature from the current release and spend more time to get the design right for the next release. 
+
+You can always add to an API, you cannot ever remove anything from one. If the design does not feel right, and you ship it anyway, you are likely to regret having done so.
+
+That's why many of the guidelines of this document are obvious and serve only one purpose: Simplicity.
+
+## Forum and Github issues
+
+Since the very beginning, Babylon.js relies on a great forum and a tremendous community: http://www.html5gamedevs.com/forum/16-babylonjs/.
+Please use the forum for **ANY questions you may have**.
+
+Please use the Github issues **only** for:
+- Bugs
+- Feature requests
+
+We will try to enforce these rules as we consider the forum is a better place for discussions and learnings.
+
+## Pull requests
+
+We are not complicated people, but we still have some [coding guidelines](http://doc.babylonjs.com/generals/Approved_Naming_Conventions)
+Before submitting your PR, just check that everything goes well by [creating the minified version](http://doc.babylonjs.com/generals/Creating_the_Mini-fied_Version)
+
+Need help contributing, here are some links:
+  - [Gulp](https://github.com/BabylonJS/Babylon.js/tree/master/Tools/Gulp) to build from command line.
+  - [VSCode Editor](https://code.visualstudio.com/), Microsoft Code editor, see [Julian Chenard's post](http://pixelcodr.com/tutos/contribute/contribute.html) a Microsoft code editor.
+  - [Visual Studio](http://doc.babylonjs.com/generals/setup_visualStudio), Microsoft's IDE.
+  - [Forum thread](http://www.html5gamedevs.com/topic/20456-contributing-on-babylonjs/) for assistance from our very helpful family.

文件差異過大導致無法顯示
+ 28 - 28
dist/preview release/babylon.core.js


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


部分文件因文件數量過多而無法顯示