Browse Source

Merge pull request #1011 from AtomicGameEngine/JME-ATOMICNET-IOS

Atomic C# iOS Support and build improvements
JoshEngebretson 9 years ago
parent
commit
8d0b515d8d
100 changed files with 9318 additions and 8323 deletions
  1. 58 0
      Build/CMake/IOS/AtomicNET.framework.plist
  2. 67 0
      Build/Scripts/Bootstrap.js
  3. 13 8
      Build/Scripts/BuildAndroid.js
  4. 44 0
      Build/Scripts/BuildAtomicNET.js
  5. 1 1
      Build/Scripts/BuildCommon.js
  6. 58 0
      Build/Scripts/BuildIOS.js
  7. 85 0
      Build/Scripts/BuildLint.js
  8. 126 63
      Build/Scripts/BuildLinux.js
  9. 114 59
      Build/Scripts/BuildMac.js
  10. 107 58
      Build/Scripts/BuildWindows.js
  11. 3 0
      Build/Scripts/Host.js
  12. 24 0
      Build/Scripts/HostCommon.js
  13. 3 3
      Build/Scripts/Windows/CompileAndroid.bat
  14. 4 0
      Build/Scripts/Windows/CompileAtomicEditorPhase1.bat
  15. 2 0
      Build/Scripts/Windows/CompileAtomicEditorPhase2.bat
  16. 1 36
      Build_AtomicEditor.bat
  17. 3 17
      Build_AtomicEditor.sh
  18. 5 5
      Script/AtomicNET/AtomicNET/Application/AppOptions.cs
  19. 8 1
      Script/AtomicNET/AtomicNET/Application/Application.cs
  20. 6 7
      Script/AtomicNET/AtomicNET/Core/AtomicNET.cs
  21. 3 1
      Script/AtomicNET/AtomicNET/Core/Constants.cs
  22. 30 13
      Script/AtomicNET/AtomicNET/Core/NativeCore.cs
  23. 0 18
      Script/AtomicNET/AtomicNET/Core/NativeEvents.cs
  24. 602 602
      Script/AtomicNET/AtomicNET/Core/SDLConsts.cs
  25. 144 0
      Script/AtomicNET/AtomicNET/Core/SDLEvents.cs
  26. 8 0
      Script/AtomicNET/AtomicNET/Graphics/Graphics.cs
  27. 914 914
      Script/AtomicNET/AtomicNET/Math/IntVector2.cs
  28. 9 9
      Script/AtomicNET/AtomicNET/Math/MathHelper.cs
  29. 766 766
      Script/AtomicNET/AtomicNET/Math/Matrix3.cs
  30. 1191 1191
      Script/AtomicNET/AtomicNET/Math/Matrix4.cs
  31. 34 34
      Script/AtomicNET/AtomicNET/Math/Plane.cs
  32. 1024 1024
      Script/AtomicNET/AtomicNET/Math/Vector2.cs
  33. 1156 1156
      Script/AtomicNET/AtomicNET/Math/Vector4.cs
  34. 26 0
      Script/AtomicNET/AtomicNETProject.json
  35. 14 14
      Script/AtomicNET/AtomicNETService/AtomicTools.cs
  36. 17 17
      Script/AtomicNET/AtomicNETService/CSComponentInspector.cs
  37. 0 7
      Script/AtomicNET/AtomicNETService/Program.cs
  38. 40 40
      Script/AtomicNET/AtomicPlayer/AtomicPlayer.Android/MainActivity.cs
  39. 31 0
      Script/AtomicNET/AtomicProject.json
  40. 10 0
      Script/AtomicNET/Platform/iOS/ApiDefinition/ApiDefinition.cs
  41. 3 0
      Script/AtomicNET/Platform/iOS/AtomicNET/AtomicNETNative.framework.linkwith.cs
  42. 1 1
      Source/Atomic/Graphics/Direct3D11/D3D11Graphics.cpp
  43. 1 1
      Source/Atomic/Graphics/Direct3D9/D3D9Graphics.cpp
  44. 1 1
      Source/Atomic/Graphics/OpenGL/OGLGraphics.cpp
  45. 9 9
      Source/Atomic/IPC/IPCWorker.cpp
  46. 6 6
      Source/Atomic/IPC/IPCWorker.h
  47. 146 146
      Source/Atomic/Input/Input.cpp
  48. 7 7
      Source/Atomic/Input/Input.h
  49. 4 4
      Source/Atomic/UI/UIDragDropWindows.cpp
  50. 4 4
      Source/Atomic/UI/UIInput.cpp
  51. 3 3
      Source/Atomic/UI/UILayout.h
  52. 4 4
      Source/Atomic/UI/UIPreferredSize.h
  53. 5 5
      Source/Atomic/UI/UIScrollContainer.h
  54. 6 6
      Source/Atomic/UI/UIWidget.h
  55. 5 5
      Source/Atomic/UI/UIWindow.h
  56. 9 9
      Source/AtomicApp/AppBase.cpp
  57. 3 3
      Source/AtomicApp/AppBase.h
  58. 12 12
      Source/AtomicEditor/EditorMode/AEEditorMode.cpp
  59. 1 1
      Source/AtomicJS/Javascript/JSComponent.h
  60. 5 5
      Source/AtomicJS/Javascript/JSEvents.h
  61. 27 0
      Source/AtomicNET/NETNative/CMakeLists.txt
  62. 8 8
      Source/AtomicNET/NETNative/Desktop/NETIPCPlayerApp.cpp
  63. 14 12
      Source/AtomicNET/NETNative/NETAtomicPlayer.cpp
  64. 53 2
      Source/AtomicNET/NETNative/NETCInterop.cpp
  65. 1 1
      Source/AtomicNET/NETScript/CSComponentAssembly.cpp
  66. 1 1
      Source/AtomicPlayer/Application/CMakeLists.txt
  67. 5 5
      Source/AtomicTool/AtomicTool.cpp
  68. 1 1
      Source/AtomicTool/CMakeLists.txt
  69. 1 1
      Source/CMakeLists.txt
  70. 30 30
      Source/ToolCore/Assets/TextureImporter.cpp
  71. 3 3
      Source/ToolCore/Assets/TextureImporter.h
  72. 10 10
      Source/ToolCore/Build/BuildBase.cpp
  73. 7 7
      Source/ToolCore/Build/BuildBase.h
  74. 22 22
      Source/ToolCore/Build/BuildWindows.cpp
  75. 1 1
      Source/ToolCore/Command/Command.h
  76. 105 71
      Source/ToolCore/Command/NETCmd.cpp
  77. 4 4
      Source/ToolCore/Command/NETCmd.h
  78. 15 15
      Source/ToolCore/JSBind/CSharp/CSFunctionWriter.cpp
  79. 27 27
      Source/ToolCore/JSBind/CSharp/CSModuleWriter.cpp
  80. 9 9
      Source/ToolCore/JSBind/CSharp/CSPackageWriter.cpp
  81. 2 2
      Source/ToolCore/JSBind/JSBEnum.cpp
  82. 158 158
      Source/ToolCore/JSBind/JSBModule.cpp
  83. 6 6
      Source/ToolCore/JSBind/JSBModule.h
  84. 38 38
      Source/ToolCore/JSBind/JSBPackage.cpp
  85. 5 5
      Source/ToolCore/JSBind/JSBPackage.h
  86. 9 9
      Source/ToolCore/JSBind/JavaScript/JSModuleWriter.cpp
  87. 49 49
      Source/ToolCore/JSBind/JavaScript/JSPackageWriter.cpp
  88. 4 4
      Source/ToolCore/NETTools/AtomicNETService.cpp
  89. 78 34
      Source/ToolCore/NETTools/NETBuildSystem.cpp
  90. 6 5
      Source/ToolCore/NETTools/NETBuildSystem.h
  91. 1327 1193
      Source/ToolCore/NETTools/NETProjectGen.cpp
  92. 47 36
      Source/ToolCore/NETTools/NETProjectGen.h
  93. 33 33
      Source/ToolCore/NETTools/NETProjectSystem.cpp
  94. 1 1
      Source/ToolCore/NETTools/NETProjectSystem.h
  95. 7 7
      Source/ToolCore/Project/Project.cpp
  96. 4 4
      Source/ToolCore/Project/Project.h
  97. 1 1
      Source/ToolCore/Project/ProjectEvents.h
  98. 167 166
      Source/ToolCore/Project/ProjectSettings.cpp
  99. 45 45
      Source/ToolCore/Project/ProjectSettings.h
  100. 1 1
      Source/ToolCore/ToolEnvironment.cpp

+ 58 - 0
Build/CMake/IOS/AtomicNET.framework.plist

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>CFBundleDevelopmentRegion</key>
+        <string>en</string>
+        <key>CFBundleIdentifier</key>
+        <string>com.atomicgameengine.atomicnetframework</string>
+        <key>CFBundleInfoDictionaryVersion</key>
+        <string>6.0</string>
+        <key>CFBundleName</key>
+        <string>Mono</string>
+        <key>CFBundlePackageType</key>
+        <string>FMWK</string>
+        <key>CFBundleShortVersionString</key>
+        <string>1.0</string>
+        <key>CFBundleSignature</key>
+        <string>????</string>
+        <key>CFBundleVersion</key>
+        <string>3.12</string>
+        <key>NSPrincipalClass</key>
+        <string></string>
+        <key>CFBundleExecutable</key>
+        <string>AtomicNETNative</string>
+
+        <key>BuildMachineOSBuild</key>
+        <string>13F34</string>
+        <key>CFBundleDevelopmentRegion</key>
+        <string>en</string>
+        <key>CFBundleSupportedPlatforms</key>
+        <array>
+                <string>iPhoneOS</string>
+        </array>
+        <key>DTCompiler</key>
+        <string>com.apple.compilers.llvm.clang.1_0</string>
+        <key>DTPlatformBuild</key>
+        <string>12D508</string>
+        <key>DTPlatformName</key>
+        <string>iphoneos</string>
+        <key>DTPlatformVersion</key>
+        <string>8.2</string>
+        <key>DTSDKBuild</key>
+        <string>12D508</string>
+        <key>DTSDKName</key>
+        <string>iphoneos8.2</string>
+        <key>DTXcode</key>
+        <string>0620</string>
+        <key>DTXcodeBuild</key>
+        <string>6C131e</string>
+        <key>MinimumOSVersion</key>
+        <string>8.0</string>
+        <key>UIDeviceFamily</key>
+        <array>
+                <integer>1</integer>
+                <integer>2</integer>
+        </array>
+</dict>
+</plist>

+ 67 - 0
Build/Scripts/Bootstrap.js

@@ -1 +1,68 @@
+
+// Load `jake` global
+require('../node_modules/jake/lib/jake');
+
+// Load jake tasks, patch in our node modules, etc
 var host = require('./Host');
+
+var os = require('os');
+
+// Parse args
+var options = require('minimist')(process.argv.slice(2));
+var cmd = options._[0];
+
+
+
+// Make options availabe to host
+host.options = options;
+
+function printHelp() {
+
+    console.log("\nAtomic Editor Build Script")
+    console.log("--------------------------")
+    console.log("--help         : This help text")
+    console.log("--with-android : Build with Android platform support");
+    console.log("--with-ios     : Build with iOS platform support");
+    console.log("--debug        : Build debug version of the editor and associated platform runtimes")
+    console.log("--noclean      : Do not clean before building, useful during development")
+    console.log("--nonet        : Build without AtomicNET C# scripting support")
+    console.log("--------------------------")
+
+    process.exit(0);
+}
+
+if (options["help"]) {
+    printHelp();
+}
+
+if (options["lint"]) {
+    var lintTask = jake.Task['build:lint'];
+    lintTask.invoke();
+}
+
+// Atomic Editor Build
+if (cmd == "buildeditor") {
+
+    console.log("\n\nBuilding Atomic Editor, this process will take a few minutes\n");
+
+    var buildTask = jake.Task['build:atomiceditor'];
+
+    if (options["with-android"]) {
+
+        if (!process.env.ANDROID_NDK) {
+            console.log("\nANDROID_NDK environment variable not set, exiting\n");
+            process.exit(1);
+        }
+    }
+
+    if (options["with-ios"]) {
+
+        if (os.platform() != "darwin") {
+            console.log("\niOS platform requires macOS, exiting\n");
+            process.exit(1);
+        }
+    }
+
+    buildTask.invoke();
+
+}

+ 13 - 8
Build/Scripts/BuildAndroid.js

@@ -2,8 +2,8 @@ var fs = require('fs-extra');
 var path = require("path");
 var host = require("./Host");
 var os = require('os');
-var atomicRoot = host.atomicRoot;
 
+var atomicRoot = host.atomicRoot;
 var buildDir = host.artifactsRoot + "Build/Android/";
 
 namespace('build', function() {
@@ -12,34 +12,39 @@ namespace('build', function() {
         async: true
     }, function() {
 
-        // Clean build
-        common.cleanCreateDir(buildDir);
+        var options = host.options;
+        var cleanBuild = options["noclean"] ? false : true;
+        var debug = options["debug"] ? true : false;
+        var config = debug ? "Debug" : "Release";
+
+
+        host.setupDirs(cleanBuild, [buildDir]);
 
         process.chdir(buildDir);
 
         var cmds = [];
 
         if (os.platform() == "win32") {
-            cmds.push(atomicRoot + "Build/Scripts/Windows/CompileAndroid.bat");
+            cmds.push(atomicRoot + "Build/Scripts/Windows/CompileAndroid.bat " + config);
         }
         else {
-            cmds.push("cmake -G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=../../../Build/CMake/Toolchains/android.toolchain.cmake -DCMAKE_BUILD_TYPE=Release ../../../");
+            cmds.push("cmake -G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=../../../Build/CMake/Toolchains/android.toolchain.cmake -DCMAKE_BUILD_TYPE="  + config + " ../../../");
             cmds.push("make -j4");
         }
 
         jake.exec(cmds, function() {
 
-            var editorAppFolder = host.artifactsRoot + (os.platform() == "win32" ? "AtomicEditor/" : "AtomicEditor/AtomicEditor.app/");
+            var editorResourceFolder = host.artifactsRoot + (os.platform() == "win32" ? "AtomicEditor/Resources/" : "AtomicEditor/AtomicEditor.app/Contents/Resources/");
 
             // Install Deployment
             fs.copySync(buildDir + "Source/AtomicPlayer/Application/libAtomicPlayer.so",
-            editorAppFolder + "Contents/Resources/ToolData/Deployment/Android/libs/armeabi-v7a/libAtomicPlayer.so");
+            editorResourceFolder + "ToolData/Deployment/Android/libs/armeabi-v7a/libAtomicPlayer.so");
 
             complete();
 
         }, {
             printStdout: true,
-            breakOnError : false
+            printStderr: true
         });
 
     });

+ 44 - 0
Build/Scripts/BuildAtomicNET.js

@@ -0,0 +1,44 @@
+var fs = require('fs-extra');
+var path = require("path");
+var host = require("./Host");
+var os = require('os');
+var atomicRoot = host.atomicRoot;
+
+namespace('build', function() {
+
+    task('atomicnet', {
+        async: true
+    }, function() {
+
+        var options = host.options;
+
+        var android = options["with-android"] ? true : false;
+        var ios = options["with-ios"] ? true : false;
+        var debug = options["debug"] ? true : false;
+
+        var cmds = [];
+
+        platforms = "-platform desktop";
+        if (android)
+            platforms += " -platform android";
+        if (ios)
+            platforms += " -platform ios";
+
+        var netCmd = host.atomicTool + " net compile " + atomicRoot + "Script/AtomicNET/AtomicNETProject.json " + platforms + " -config " + (debug ? "Debug" : "Release");
+
+        console.log(netCmd);
+        
+        cmds.push(netCmd);
+
+        jake.exec(cmds, function() {
+
+            complete();
+
+        }, {
+            printStdout: true,
+            printStderr: true
+        });
+
+    });
+
+}); // end of build namespace

+ 1 - 1
Build/Scripts/BuildCommon.js

@@ -89,7 +89,7 @@ namespace('build', function() {
       // Compile AtomicNET assemblies
       var cmds = [];
 
-      cmds.push(host.atomicTool + " net compile " + atomicRoot + "Script/AtomicNET/AtomicNETProject.json " + platform + " " + configuration);
+      cmds.push(host.atomicTool + " net compile " + atomicRoot + "Script/AtomicNET/AtomicNETProject.json -platform " + platform + " -config " + configuration);
 
       jake.exec(cmds, function() {
 

+ 58 - 0
Build/Scripts/BuildIOS.js

@@ -0,0 +1,58 @@
+var fs = require('fs-extra');
+var path = require("path");
+var host = require("./Host");
+var os = require('os');
+
+var jenkinsBuild = process.env.ATOMIC_JENKINS_BUILD == 1;
+
+var atomicRoot = host.atomicRoot;
+var buildDir = host.artifactsRoot + "Build/IOS/";
+
+namespace('build', function() {
+
+    task('ios_native', {
+        async: true
+    }, function() {
+
+        var options = host.options;
+        var cleanBuild = options["noclean"] ? false : true;
+        var debug = options["debug"] ? true : false;
+
+        var NETNativeSrcDir = buildDir + "Source/AtomicNET/NETNative/" + (debug ? "Debug" : "Release") + "-iphoneos/";
+        var NETNativeDestDir = host.artifactsRoot + "AtomicNET/" + (debug ? "Debug" : "Release") + "/Native/iOS/";
+
+        host.setupDirs(cleanBuild, [buildDir, NETNativeDestDir]);
+
+        process.chdir(buildDir);
+
+        var cmds = [];
+
+        cmds.push("cmake -DIOS=1 -DATOMIC_DEV_BUILD=0 -G Xcode ../../../");
+
+
+        if (jenkinsBuild) {
+            cmds.push("security -v list-keychains -d system -s /Users/jenkins/Library/Keychains/codesign.keychain");
+            cmds.push("security -v unlock-keychain /Users/jenkins/Library/Keychains/codesign.keychain");
+        }
+
+        cmds.push("xcodebuild -configuration " + (debug ? "Debug" : "Release") + " -parallelizeTargets -jobs 4");
+        // Note that this install_name_tool invocation invalidates the code signing, Xamarin/Visual Studio should resign the binary on deploy to device
+        cmds.push("cd \"" + NETNativeSrcDir + "\" && install_name_tool -id @rpath/AtomicNETNative.framework/AtomicNETNative AtomicNETNative.framework/AtomicNETNative");
+        //cmds.push("cd \"" + NETNativeSrcDir + "\" && codesign --deep --force --verify --sign \"iPhone Developer\" ./AtomicNETNative.framework/");
+        cmds.push("cd \"" + NETNativeSrcDir + "\" && zip -r AtomicNETNative.framework.zip AtomicNETNative.framework");
+
+        jake.exec(cmds, function() {
+
+            fs.copySync(NETNativeSrcDir + "AtomicNETNative.framework", NETNativeDestDir + "AtomicNETNative.framework");
+            fs.copySync(NETNativeSrcDir + "AtomicNETNative.framework.zip", NETNativeDestDir + "AtomicNETNative.framework.zip");
+
+            complete();
+
+        }, {
+            printStdout: true,
+            printStderr: true
+        });
+
+    });
+
+}); // end of build namespace

+ 85 - 0
Build/Scripts/BuildLint.js

@@ -0,0 +1,85 @@
+var fs = require('fs-extra');
+var path = require("path");
+var host = require("./Host");
+var os = require('os');
+var glob = require("glob");
+
+var fixTabs = false;
+
+var atomicRoot = host.atomicRoot;
+
+// Oh, JavaScript
+atomicRoot = atomicRoot.split("\\");
+atomicRoot = atomicRoot.join("/");
+
+function lintFile(filename) {
+
+    var file = fs.readFileSync(filename, "utf-8");
+
+    if (file.indexOf('\t') != -1) {
+
+        console.log(filename + "  contains tab character");
+
+        if (fixTabs) {
+            
+            var fd = fs.openSync(filename, "w");
+
+            var tabbed = file.split('\t');
+            file = tabbed.join("    ");
+
+            fs.writeSync(fd, file);
+            fs.closeSync(fd);
+        }
+    }
+
+}
+
+namespace('build', function() {
+
+    task('lint', {
+        async: true
+    }, function() {
+
+        // I looked into options and there are many for C# and C++, though simply want to catch tabs/spaces right now
+        // and not introduce a dependency, soooooo
+
+        pattern = [ atomicRoot + "Source/**/*.cpp",
+                    atomicRoot + "Source/**/*.h",
+                    atomicRoot + "Script/AtomicNET/**/*.cs"
+                 ];
+
+        pattern = "{" + pattern.join(",") + "}";
+
+        // I failed at figure out glob exclusion patterns
+        exclude = [atomicRoot + "Source/ThirdParty/",
+                   atomicRoot + "Source/ToolCore/JSBind/cplusplus/"];
+
+        var filenames = glob.sync(pattern);
+
+        for (var i = 0; i < filenames.length; i++) {
+
+            var filename = filenames[i];
+
+            var skip = false;
+
+            for (var j = 0; j < exclude.length; j++) {
+
+                if (filename.startsWith(exclude[j])) {
+                    skip = true;
+                    break;
+                }
+            }
+
+            if (skip)
+                continue;
+
+            lintFile(filename);
+        }
+
+
+        process.exit(0);
+        complete();
+
+    });
+
+}); // end of build namespace

+ 126 - 63
Build/Scripts/BuildLinux.js

@@ -1,106 +1,169 @@
 var fs = require('fs-extra');
 var path = require("path");
-var spawnSync = require('child_process').spawnSync
 var host = require("./Host");
-var atomicRoot = host.atomicRoot;
+var spawnSync = require('child_process').spawnSync
 
+var atomicRoot = host.atomicRoot;
 var buildDir = host.artifactsRoot + "Build/Linux/";
 var editorAppFolder = host.artifactsRoot + "AtomicEditor/";
 
-namespace('build', function() {
+var buildAtomicNET = false;
+var debug = false;
+var config = "Release";
 
-    // Builds a standalone Atomic Editor, which can be distributed out of build tree
-    task('atomiceditor', {
-        async: true
-    }, function() {
+function copyAtomicNET() {
 
-        // Clean build
-        var cleanBuild = true;
-        if (cleanBuild) {
-            common.cleanCreateDir(buildDir);
-            common.cleanCreateDir(editorAppFolder);
-            common.cleanCreateDir(host.getGenScriptRootDir("LINUX"));
-        }
+    if (!buildAtomicNET)
+        return;
 
-        var buildAtomicNET = false;
+    fs.copySync(atomicRoot + "Artifacts/AtomicNET/" + config,
+    editorAppFolder + "Resources/ToolData/AtomicNET/" + config);
 
-        // TODO: build box has old node
-        if (spawnSync)
-            buildAtomicNET = spawnSync("which", ["xbuild"]).status == 1 ? false : true;
+    fs.copySync(atomicRoot + "Script/AtomicNET/AtomicProject.json",
+    editorAppFolder + "Resources/ToolData/AtomicNET/Build/Projects/AtomicProject.json");
+
+}
+
+function copyAtomicEditor() {
+
+    // Copy the Editor binaries
+    fs.copySync(buildDir + "Source/AtomicEditor/AtomicEditor",
+    host.artifactsRoot + "AtomicEditor/AtomicEditor");
+
+    // We need some resources to run
+    fs.copySync(atomicRoot + "Resources/CoreData",
+    editorAppFolder + "Resources/CoreData");
+
+    fs.copySync(atomicRoot + "Resources/PlayerData",
+    editorAppFolder + "Resources/PlayerData");
+
+    fs.copySync(atomicRoot + "Data/AtomicEditor",
+    editorAppFolder + "Resources/ToolData");
+
+    fs.copySync(atomicRoot + "Resources/EditorData",
+    editorAppFolder + "Resources/EditorData");
+
+    fs.copySync(atomicRoot + "Artifacts/Build/Resources/EditorData/AtomicEditor/EditorScripts",
+    editorAppFolder + "Resources/EditorData/AtomicEditor/EditorScripts");
+
+    fs.copySync(buildDir +  "Source/AtomicPlayer/Application/AtomicPlayer",
+    editorAppFolder + "Resources/ToolData/Deployment/Linux/AtomicPlayer");
+
+    var binaryFiles = ["chrome-sandbox", "libcef.so", "natives_blob.bin", "snapshot_blob.bin"];
+
+    var resourceFiles = ["cef.pak",
+    "cef_100_percent.pak",
+    "cef_200_percent.pak",
+    "cef_extensions.pak",
+    "devtools_resources.pak",
+    "icudtl.dat",
+    "locales"];
+
+    for (var i = 0; i < binaryFiles.length; i++) {
+        fs.copySync(atomicRoot + "Submodules/CEF/Linux/Release/" + binaryFiles[i], editorAppFolder+"/" + binaryFiles[i]);
+    }
+
+    for (var i = 0; i < resourceFiles.length; i++) {
+        fs.copySync(atomicRoot + "Submodules/CEF/Linux/Resources/" + resourceFiles[i], editorAppFolder+"/" + resourceFiles[i]);
+    }
+
+
+    if (buildAtomicNET) {
+        copyAtomicNET();
+    }
+
+}
+
+namespace('build', function() {
+
+    task('atomiceditor_phase2', {
+        async: true
+    }, function() {
 
         process.chdir(buildDir);
 
         var cmds = [];
+        cmds.push("make AtomicEditor AtomicPlayer -j2")
 
-        cmds.push("cmake ../../../ -DATOMIC_DEV_BUILD=0 -DCMAKE_BUILD_TYPE=Release");
-        cmds.push("make -j2")
+        jake.exec(cmds, function() {
 
-        if (buildAtomicNET)
-          cmds.push(host.atomicTool + " net compile " + atomicRoot + "Script/AtomicNET/AtomicNETProject.json LINUX Release");
+            copyAtomicEditor();
 
-        jake.exec(cmds, function() {
+            complete();
 
-            // Copy the Editor binaries
-            fs.copySync(buildDir + "Source/AtomicEditor/AtomicEditor",
-            host.artifactsRoot + "AtomicEditor/AtomicEditor");
+        }, {
+            printStdout: true
+        });
 
-            // We need some resources to run
-            fs.copySync(atomicRoot + "Resources/CoreData",
-            editorAppFolder + "Resources/CoreData");
+    });
+    // Builds a standalone Atomic Editor, which can be distributed out of build tree
+    task('atomiceditor', {
+        async: true
+    }, function() {
 
-            fs.copySync(atomicRoot + "Resources/PlayerData",
-            editorAppFolder + "Resources/PlayerData");
+        var options = host.options;
 
-            fs.copySync(atomicRoot + "Data/AtomicEditor",
-            editorAppFolder + "Resources/ToolData");
+        var android = options["with-android"] ? true : false;
+        var cleanBuild = options["noclean"] ? false : true;
+        debug = options["debug"] ? true : false;
+        config = debug ? "Debug" : "Release";
 
-            fs.copySync(atomicRoot + "Resources/EditorData",
-            editorAppFolder + "Resources/EditorData");
+        var createDirs = [];
+        var removeDirs = [];
 
-            fs.copySync(atomicRoot + "Artifacts/Build/Resources/EditorData/AtomicEditor/EditorScripts",
-            editorAppFolder + "Resources/EditorData/AtomicEditor/EditorScripts");
+        // We clean atomicNET here as otherwise platform binaries would be deleted
+        createDirs.push(host.artifactsRoot + "AtomicNET/");
+        createDirs.push(buildDir);
+        createDirs.push(editorAppFolder);
+        createDirs.push(host.getGenScriptRootDir());
 
-            fs.copySync(buildDir +  "Source/AtomicPlayer/Application/AtomicPlayer",
-            editorAppFolder + "Resources/ToolData/Deployment/Linux/AtomicPlayer");
+        removeDirs.push(host.artifactsRoot + "Build/Android/");
 
-            // AtomicNET
+        host.setupDirs(cleanBuild, createDirs, removeDirs);
 
-            if (buildAtomicNET) {
+        // TODO: build box has old node
+        if (spawnSync)
+            buildAtomicNET = spawnSync("which", ["xbuild"]).status == 1 ? false : true;
 
-              fs.copySync(atomicRoot + "Artifacts/AtomicNET/Release",
-                 editorAppFolder + "Resources/ToolData/AtomicNET/Release");
+        process.chdir(buildDir);
 
-              fs.copySync(atomicRoot + "Script/AtomicNET/AtomicProject.json",
-                 editorAppFolder + "Resources/ToolData/AtomicNET/Build/Projects/AtomicProject.json");
-            }
+        var cmds = [];
 
-            var binaryFiles = ["chrome-sandbox", "libcef.so", "natives_blob.bin", "snapshot_blob.bin"];
+        // Generate Atomic solution, AtomicTool binary, and script bindings
+        cmds.push("cmake ../../../ -DATOMIC_DEV_BUILD=0 -DCMAKE_BUILD_TYPE=" + config);
+        cmds.push("make AtomicNETNative -j2")
 
-            var resourceFiles = ["cef.pak",
-            "cef_100_percent.pak",
-            "cef_200_percent.pak",
-            "cef_extensions.pak",
-            "devtools_resources.pak",
-            "icudtl.dat",
-            "locales"];
+        jake.exec(cmds, function() {
+
+            var rootTask = jake.Task['build:atomiceditor_phase2'];
+            var task = rootTask;
 
-            for (var i = 0; i < binaryFiles.length; i++) {
-                fs.copySync(atomicRoot + "Submodules/CEF/Linux/Release/" + binaryFiles[i], editorAppFolder+"/" + binaryFiles[i]);
+            // add optional build components in reverse order
+            if (buildAtomicNET) {
+                var netTask = jake.Task['build:atomicnet'];
+                task.prereqs.push("build:atomicnet")
+                task = netTask;
             }
 
-            for (var i = 0; i < resourceFiles.length; i++) {
-                fs.copySync(atomicRoot + "Submodules/CEF/Linux/Resources/" + resourceFiles[i], editorAppFolder+"/" + resourceFiles[i]);
+            if (android) {
+                var androidTask = jake.Task['build:android_native'];
+                task.prereqs.push("build:android_native")
+                task = androidTask;
             }
 
+            rootTask.addListener('complete', function () {
+                console.log("\n\nAtomic Editor built to " + editorAppFolder + "\n\n");
+                complete();
+            });
 
-            console.log("\n\nAtomic Editor build to " + editorAppFolder + "\n\n");
-
-            complete();
+            rootTask.invoke();
 
         }, {
-            printStdout: true
+            printStdout: true,
+            printStderr: true
         });
 
     });
 
-});
+
+});// end of build namespace

+ 114 - 59
Build/Scripts/BuildMac.js

@@ -2,102 +2,156 @@ var fs = require('fs-extra');
 var path = require("path");
 var spawnSync = require('child_process').spawnSync
 var host = require("./Host");
-var atomicRoot = host.atomicRoot;
 
+var atomicRoot = host.atomicRoot;
 var buildDir = host.artifactsRoot + "Build/Mac/";
 var editorAppFolder = host.artifactsRoot + "/AtomicEditor/AtomicEditor.app/";
 var resourceDest = editorAppFolder + "/Contents/Resources/"
 
-namespace('build', function() {
+var buildAtomicNET = false;
+var debug = false;
+var config = "Release";
 
-    // Builds a standalone Atomic Editor, which can be distributed out of build tree
-    task('atomiceditor', {
-        async: true
-    }, function(android) {
+function copyAtomicNET() {
 
-        android = android == "android" ? true : false;
+    if (!buildAtomicNET)
+        return;
 
-        // Clean build
-        var cleanBuild = true;
-        if (cleanBuild) {
-            common.cleanCreateDir(host.artifactsRoot + "AtomicNET/");
-            common.cleanCreateDir(buildDir);
-            common.cleanCreateDir(editorAppFolder);
-            common.cleanCreateDir(host.getGenScriptRootDir());
-        }
+    fs.copySync(atomicRoot + "Artifacts/AtomicNET/" + config,
+    resourceDest + "ToolData/AtomicNET/" + config);
 
-        var buildAtomicNET = spawnSync("which", ["xbuild"]).status == 1 ? false : true;
+    fs.copySync(atomicRoot + "Script/AtomicNET/AtomicProject.json",
+    resourceDest + "ToolData/AtomicNET/Build/Projects/AtomicProject.json");
 
-        process.chdir(buildDir);
+}
 
-        var cmds = [];
+function copyAtomicEditor() {
 
-        cmds.push("cmake ../../../ -DATOMIC_DEV_BUILD=0 -G Xcode");
-        cmds.push("xcodebuild -target AtomicEditor -target AtomicPlayer -target AtomicNETNative -configuration Release -parallelizeTargets -jobs 4")
+    fs.copySync(buildDir + "Source/AtomicEditor/" + config + "/AtomicEditor.app", editorAppFolder);
 
-        if (buildAtomicNET)
-            cmds.push(host.atomicTool + " net compile " + atomicRoot + "Script/AtomicNET/AtomicNETProject.json " + (android ? "ANDROID" : "WINDOWS") + " Release");
+    // We need some resources to run
+    fs.copySync(atomicRoot + "Resources/CoreData",
+    resourceDest + "CoreData");
 
-        function copyAtomicNET() {
+    fs.copySync(atomicRoot + "Resources/PlayerData",
+    resourceDest + "PlayerData");
 
-            if (!buildAtomicNET)
-                return;
+    fs.copySync(atomicRoot + "Data/AtomicEditor",
+    resourceDest + "ToolData");
 
-            fs.copySync(atomicRoot + "Artifacts/AtomicNET/Release",
-            resourceDest + "ToolData/AtomicNET/Release");
+    fs.copySync(atomicRoot + "Resources/EditorData",
+    resourceDest + "EditorData");
 
-            fs.copySync(atomicRoot + "Script/AtomicNET/AtomicProject.json",
-            resourceDest + "ToolData/AtomicNET/Build/Projects/AtomicProject.json");
+    fs.copySync(atomicRoot + "Artifacts/Build/Resources/EditorData/AtomicEditor/EditorScripts",
+    resourceDest + "EditorData/AtomicEditor/EditorScripts");
 
-        }
+    // copy the mac player binary to deployment
+    var playerBinary =  buildDir +  "Source/AtomicPlayer/Application/" + config + "/AtomicPlayer.app/Contents/MacOS/AtomicPlayer";
+
+    fs.copySync(playerBinary, resourceDest + "ToolData/Deployment/MacOS/AtomicPlayer.app/Contents/MacOS/AtomicPlayer");
+
+    if (buildAtomicNET) {
+        copyAtomicNET();
+    }
 
+}
+
+namespace('build', function() {
+
+    task('atomiceditor_phase2', {
+        async: true
+    }, function() {
+
+        process.chdir(buildDir);
+
+        var cmds = [];
+        cmds.push("xcodebuild -target AtomicEditor -target AtomicPlayer -configuration " + config + " -parallelizeTargets -jobs 4")
 
         jake.exec(cmds, function() {
 
-            fs.copySync(buildDir + "Source/AtomicEditor/Release/AtomicEditor.app", editorAppFolder);
+            copyAtomicEditor();
+
+            complete();
+
+        }, {
+            printStdout: true
+        });
+
+    });
 
-            // We need some resources to run
-            fs.copySync(atomicRoot + "Resources/CoreData",
-            resourceDest + "CoreData");
+    // Builds a standalone Atomic Editor, which can be distributed out of build tree
+    task('atomiceditor', {
+        async: true
+    }, function() {
 
-            fs.copySync(atomicRoot + "Resources/PlayerData",
-            resourceDest + "PlayerData");
+        var options = host.options;
 
-            fs.copySync(atomicRoot + "Data/AtomicEditor",
-            resourceDest + "ToolData");
+        var android = options["with-android"] ? true : false;
+        var ios = options["with-ios"] ? true : false;
+        var cleanBuild = options["noclean"] ? false : true;
+        debug = options["debug"] ? true : false;
+        config = debug ? "Debug" : "Release";
 
-            fs.copySync(atomicRoot + "Resources/EditorData",
-            resourceDest + "EditorData");
+        var createDirs = [];
+        var removeDirs = [];
 
-            fs.copySync(atomicRoot + "Artifacts/Build/Resources/EditorData/AtomicEditor/EditorScripts",
-            resourceDest + "EditorData/AtomicEditor/EditorScripts");
+        // We clean atomicNET here as otherwise platform binaries would be deleted
+        createDirs.push(host.artifactsRoot + "AtomicNET/");
+        createDirs.push(buildDir);
+        createDirs.push(editorAppFolder);
+        createDirs.push(host.getGenScriptRootDir());
 
-            // copy the mac player binary to deployment
-            var playerBinary =  buildDir +  "Source/AtomicPlayer/Application/Release/AtomicPlayer.app/Contents/MacOS/AtomicPlayer";
+        removeDirs.push(host.artifactsRoot + "Build/Android/");
+        removeDirs.push(host.artifactsRoot + "Build/IOS/");
 
-            fs.copySync(playerBinary, resourceDest + "ToolData/Deployment/MacOS/AtomicPlayer.app/Contents/MacOS/AtomicPlayer");
+        host.setupDirs(cleanBuild, createDirs, removeDirs);
 
-            if (android) {
+        if (!options["nonet"]) {
+            buildAtomicNET = spawnSync("which", ["xbuild"]).status == 1 ? false : true;
+        }
+
+        process.chdir(buildDir);
+
+        var cmds = [];
 
-                var androidNativeTask = jake.Task['build:android_native'];
+        // Generate XCode project, AtomicTool binary, and script bindings
+        cmds.push("cmake ../../../ -DATOMIC_DEV_BUILD=0 -G Xcode");
+        cmds.push("xcodebuild -target GenerateScriptBindings -target AtomicNETNative -configuration " + config + " -parallelizeTargets -jobs 4")
 
-                androidNativeTask.addListener('complete', function () {
-                    copyAtomicNET();
-                    console.log("\n\nAtomic Editor build to " + editorAppFolder + "\n\n");
-                    complete();
-                });
+        jake.exec(cmds, function() {
 
-                androidNativeTask.invoke();
+            var rootTask = jake.Task['build:atomiceditor_phase2'];
+            var task = rootTask;
 
+            // add optional build components in reverse order
+            if (buildAtomicNET) {
+                var netTask = jake.Task['build:atomicnet'];
+                task.prereqs.push("build:atomicnet")
+                task = netTask;
             }
-            else {
-                copyAtomicNET();
-                console.log("\n\nAtomic Editor build to " + editorAppFolder + "\n\n");
-                complete();
+
+            if (ios) {
+                var iosTask = jake.Task['build:ios_native'];
+                task.prereqs.push("build:ios_native")
+                task = iosTask;
             }
 
+            if (android) {
+                var androidTask = jake.Task['build:android_native'];
+                task.prereqs.push("build:android_native")
+                task = androidTask;
+            }
+
+            rootTask.addListener('complete', function () {
+                console.log("\n\nAtomic Editor built to " + editorAppFolder + "\n\n");
+                complete();
+            });
+
+            rootTask.invoke();
+
         }, {
-            printStdout: true
+            printStdout: true,
+            printStderr: true
         });
 
     });
@@ -124,7 +178,8 @@ namespace('build', function() {
             complete();
 
         }, {
-            printStdout: true
+            printStdout: true,
+            printStderr: true
         });
 
     });

+ 107 - 58
Build/Scripts/BuildWindows.js

@@ -1,96 +1,144 @@
 var fs = require('fs-extra');
 var path = require("path");
 var host = require("./Host");
-var atomicRoot = host.atomicRoot;
 
+var atomicRoot = host.atomicRoot;
 var buildDir = host.artifactsRoot + "Build/Windows/";
 var editorAppFolder = host.artifactsRoot + "AtomicEditor/";
 
-namespace('build', function() {
+var buildAtomicNET = true;
+var debug = false;
+var config = "Release";
 
-    // Builds a standalone Atomic Editor, which can be distributed out of build tree
-    task('atomiceditor', {
-        async: true
-    }, function(android) {
+function copyAtomicNET() {
 
-        android = android == "android" ? true : false;
+    if (!buildAtomicNET)
+        return;
 
-        // Clean build
-        var cleanBuild = true;
-        if (cleanBuild) {
-            common.cleanCreateDir(host.artifactsRoot + "AtomicNET/");
-            common.cleanCreateDir(buildDir);
-            common.cleanCreateDir(editorAppFolder);
-            common.cleanCreateDir(host.getGenScriptRootDir());
-        }
+    fs.copySync(atomicRoot + "Artifacts/AtomicNET/" + config,
+    editorAppFolder + "Resources/ToolData/AtomicNET/" + config);
 
-        process.chdir(buildDir);
+    fs.copySync(atomicRoot + "Script/AtomicNET/AtomicProject.json",
+    editorAppFolder + "Resources/ToolData/AtomicNET/Build/Projects/AtomicProject.json");
 
-        var cmds = [];
+}
 
-        // Build the AtomicEditor
-        cmds.push(atomicRoot + "Build/Scripts/Windows/CompileAtomicEditor.bat");
-        cmds.push(host.atomicTool + " net compile " + atomicRoot + "Script/AtomicNET/AtomicNETProject.json " + (android ? "ANDROID" : "WINDOWS") + " Release");
+function copyAtomicEditor() {
 
-        function copyAtomicNET() {
+    // Copy the Editor binaries
+    fs.copySync(buildDir + "Source/AtomicEditor/" + config,
+    host.artifactsRoot + "AtomicEditor");
 
-            fs.copySync(atomicRoot + "Artifacts/AtomicNET/Release",
-            editorAppFolder + "Resources/ToolData/AtomicNET/Release");
+    // We need some resources to run
+    fs.copySync(atomicRoot + "Resources/CoreData",
+    editorAppFolder + "Resources/CoreData");
 
-            fs.copySync(atomicRoot + "Script/AtomicNET/AtomicProject.json",
-            editorAppFolder + "Resources/ToolData/AtomicNET/Build/Projects/AtomicProject.json");
+    fs.copySync(atomicRoot + "Resources/PlayerData",
+    editorAppFolder + "Resources/PlayerData");
 
-        }
+    fs.copySync(atomicRoot + "Data/AtomicEditor",
+    editorAppFolder + "Resources/ToolData");
+
+    fs.copySync(atomicRoot + "Resources/EditorData",
+    editorAppFolder + "Resources/EditorData");
+
+    fs.copySync(atomicRoot + "Artifacts/Build/Resources/EditorData/AtomicEditor/EditorScripts",
+    editorAppFolder + "Resources/EditorData/AtomicEditor/EditorScripts");
+
+    fs.copySync(buildDir +  "Source/AtomicPlayer/Application/" + config +"/AtomicPlayer.exe",
+    editorAppFolder + "Resources/ToolData/Deployment/Windows/x64/AtomicPlayer.exe");
+
+    fs.copySync(buildDir +  "Source/AtomicPlayer/Application/" + config + "/D3DCompiler_47.dll",
+    editorAppFolder + "Resources/ToolData/Deployment/Windows/x64/D3DCompiler_47.dll");
+
+    if (buildAtomicNET) {
+        copyAtomicNET();
+    }
+
+}
+
+namespace('build', function() {
+
+    task('atomiceditor_phase2', {
+        async: true
+    }, function() {
+
+        process.chdir(buildDir);
+
+        var cmds = [];
+        cmds.push(atomicRoot + "Build/Scripts/Windows/CompileAtomicEditorPhase2.bat " + config);
 
         jake.exec(cmds, function() {
 
-            // Copy the Editor binaries
-            fs.copySync(buildDir + "Source/AtomicEditor/Release",
-            host.artifactsRoot + "AtomicEditor");
+            copyAtomicEditor();
 
-            // We need some resources to run
-            fs.copySync(atomicRoot + "Resources/CoreData",
-            editorAppFolder + "Resources/CoreData");
+            complete();
+
+        }, {
+            printStdout: true
+        });
 
-            fs.copySync(atomicRoot + "Resources/PlayerData",
-            editorAppFolder + "Resources/PlayerData");
+    });
+    // Builds a standalone Atomic Editor, which can be distributed out of build tree
+    task('atomiceditor', {
+        async: true
+    }, function() {
 
-            fs.copySync(atomicRoot + "Data/AtomicEditor",
-            editorAppFolder + "Resources/ToolData");
+        var options = host.options;
 
-            fs.copySync(atomicRoot + "Resources/EditorData",
-            editorAppFolder + "Resources/EditorData");
+        var android = options["with-android"] ? true : false;
+        var cleanBuild = options["noclean"] ? false : true;
+        debug = options["debug"] ? true : false;
+        config = debug ? "Debug" : "Release";
 
-            fs.copySync(atomicRoot + "Artifacts/Build/Resources/EditorData/AtomicEditor/EditorScripts",
-            editorAppFolder + "Resources/EditorData/AtomicEditor/EditorScripts");
+        var createDirs = [];
+        var removeDirs = [];
 
-            fs.copySync(buildDir +  "Source/AtomicPlayer/Application/Release/AtomicPlayer.exe",
-            editorAppFolder + "Resources/ToolData/Deployment/Windows/x64/AtomicPlayer.exe");
+        // We clean atomicNET here as otherwise platform binaries would be deleted
+        createDirs.push(host.artifactsRoot + "AtomicNET/");
+        createDirs.push(buildDir);
+        createDirs.push(editorAppFolder);
+        createDirs.push(host.getGenScriptRootDir());
 
-            fs.copySync(buildDir +  "Source/AtomicPlayer/Application/Release/D3DCompiler_47.dll",
-            editorAppFolder + "Resources/ToolData/Deployment/Windows/x64/D3DCompiler_47.dll");
+        removeDirs.push(host.artifactsRoot + "Build/Android/");
 
-            if (android) {
+        host.setupDirs(cleanBuild, createDirs, removeDirs);
 
-                var androidNativeTask = jake.Task['build:android_native'];
+        process.chdir(buildDir);
 
-                androidNativeTask.addListener('complete', function () {
-                    copyAtomicNET();
-                    console.log("\nAtomic Editor build to ", editorAppFolder);
-                    complete();
-                });
+        var cmds = [];
 
-                androidNativeTask.invoke();
+        // Generate Atomic solution, AtomicTool binary, and script bindings
+        cmds.push(atomicRoot + "Build/Scripts/Windows/CompileAtomicEditorPhase1.bat " + config);
 
+        jake.exec(cmds, function() {
+
+            var rootTask = jake.Task['build:atomiceditor_phase2'];
+            var task = rootTask;
+
+            // add optional build components in reverse order
+            if (buildAtomicNET) {
+                var netTask = jake.Task['build:atomicnet'];
+                task.prereqs.push("build:atomicnet")
+                task = netTask;
             }
-            else {
-                copyAtomicNET();
-                console.log("\nAtomic Editor build to ", editorAppFolder);
-                complete();
+
+            if (android) {
+                var androidTask = jake.Task['build:android_native'];
+                task.prereqs.push("build:android_native")
+                task = androidTask;
             }
 
+            rootTask.addListener('complete', function () {
+                console.log("\n\nAtomic Editor built to " + editorAppFolder + "\n\n");
+                complete();
+            });
+
+            rootTask.invoke();
+
         }, {
-            printStdout: true
+            printStdout: true,
+            printStderr: true
         });
 
     });
@@ -124,4 +172,5 @@ namespace('build', function() {
 
     });
 
-}); // end of build namespace
+
+});// end of build namespace

+ 3 - 0
Build/Scripts/Host.js

@@ -13,4 +13,7 @@ if (os.platform() == "win32") {
 
 require("./BuildCommon");
 require("./BuildAndroid");
+require("./BuildIOS");
 require("./BuildWeb");
+require("./BuildAtomicNET");
+require("./BuildLint");

+ 24 - 0
Build/Scripts/HostCommon.js

@@ -138,6 +138,29 @@ function testCreateDir(directory) {
   }
 }
 
+function setupDirs(clean, createDirs, removeDirs) {
+
+    if (createDirs) {
+        for (var i = 0; i < createDirs.length; i++) {
+
+            var path = createDirs[i];
+            if (!fs.existsSync(path) || clean) {
+                cleanCreateDir(path);
+            }
+        }
+    }
+
+    if (removeDirs) {
+        for (var i = 0; i < removeDirs.length; i++) {
+
+            var path = removeDirs[i];
+            if (fs.existsSync(path) && clean) {
+                testRemoveDir(path);
+            }
+        }
+    }
+
+}
 
 function testRemoveDir(path) {
 
@@ -160,3 +183,4 @@ exports.getScriptModules = getScriptModules;
 exports.getGenScriptFilenames = getGenScriptFilenames;
 exports.createGenScriptFiles = createGenScriptFiles;
 exports.getGenScriptRootDir = getGenScriptRootDir;
+exports.setupDirs = setupDirs;

+ 3 - 3
Build/Scripts/Windows/CompileAndroid.bat

@@ -1,3 +1,3 @@
-SET PATH=%ANDROID_NDK%\prebuilt\windows\bin\;%PATH%
-cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=../../../Build/CMake/Toolchains/android.toolchain.cmake -DCMAKE_BUILD_TYPE=Release ../../../
-%ANDROID_NDK%\prebuilt\windows\bin\make.exe -j4
+SET PATH=%ANDROID_NDK%\prebuilt\windows-x86_64\bin\;%ANDROID_NDK%\prebuilt\windows\bin\;%PATH%
+cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=../../../Build/CMake/Toolchains/android.toolchain.cmake -DCMAKE_BUILD_TYPE=%1 ../../../
+make.exe -j4

+ 4 - 0
Build/Scripts/Windows/CompileAtomicEditorPhase1.bat

@@ -0,0 +1,4 @@
+call "%VS140COMNTOOLS%..\..\VC\bin\amd64\vcvars64.bat"
+cmake ..\\..\\..\\ -DATOMIC_DEV_BUILD=0 -G "Visual Studio 14 2015 Win64"
+:: Note, we're building LibCpuId as it uses masm as getting XamlFactory load errors if delayed
+msbuild /m Atomic.sln /t:LibCpuId /t:AtomicNETNative /p:Configuration=%1 /p:Platform=x64

+ 2 - 0
Build/Scripts/Windows/CompileAtomicEditorPhase2.bat

@@ -0,0 +1,2 @@
+call "%VS140COMNTOOLS%..\..\VC\bin\amd64\vcvars64.bat"
+msbuild /m Atomic.sln /t:AtomicEditor /t:AtomicPlayer /p:Configuration=%1 /p:Platform=x64

+ 1 - 36
Build_AtomicEditor.bat

@@ -1,37 +1,2 @@
 @echo OFF
-setlocal enabledelayedexpansion
-
-set ATOMICEDITOR_BUILD_CMD=Build\Windows\node\node.exe Build\node_modules\jake\bin\cli.js -f ./Build/Scripts/Bootstrap.js build:atomiceditor
-
-for %%a in (%*) do (
-  if /I "%%a"=="--with-android" (set ATOMICEDITOR_ANDROID=YES)
-)
-
-:: If we're building in android support, make sure ANDROID_NDK is defined
-if "%ATOMICEDITOR_ANDROID%" == "YES" (
-
-    if "%ANDROID_NDK%" == "" (
-        @echo:
-        echo ANDROID_NDK not set, exiting
-        @echo:
-        exit /B
-    )
-
-    @echo:
-    echo Building Atomic Editor with Android support
-    @echo:
-    set ATOMICEDITOR_BUILD_CMD=!ATOMICEDITOR_BUILD_CMD![android]
-)
-
-@echo:
-@echo:
-ECHO Building Atomic Editor, this process will take a few minutes
-@echo:
-@echo:
-PAUSE
-%ATOMICEDITOR_BUILD_CMD%
-@echo:
-@echo:
-PAUSE
-
-endlocal
+Build\Windows\node\node.exe ./Build/Scripts/Bootstrap.js buildeditor %*

+ 3 - 17
Build_AtomicEditor.sh

@@ -1,23 +1,9 @@
 #!/usr/bin/env sh
 
-buildcmd="build:atomiceditor"
-
-for var in "$@"
-do
-    if [ $var == "--with-android" ]; then
-        if [ "$ANDROID_NDK" == "" ]; then
-            echo "\n\nANDROID_NDK environment variable not set, exiting\n\n"
-            exit 1
-        fi
-        echo "\n\nBuilding Atomic Editor with Android support\n\n"
-        buildcmd+="[android]"
-    fi
-done
-
 if [ "$(uname)" = "Darwin" ]; then
-    ./Build/Mac/node/node ./Build/node_modules/jake/bin/cli.js -f ./Build/Scripts/Bootstrap.js $buildcmd
+    ./Build/Mac/node/node ./Build/Scripts/Bootstrap.js buildeditor "$@"
 elif [ "$(expr substr $(uname -s) 1 5)" = "Linux" ]; then
-    ./Build/Linux/node/node ./Build/node_modules/jake/bin/cli.js -f ./Build/Scripts/Bootstrap.js $buildcmd
+    ./Build/Linux/node/node ./Build/Scripts/Bootstrap.js buildeditor "$@"
 elif [ "$(expr substr $(uname -s) 1 7)" = "MSYS_NT" ]; then
-    ./Build/Windows/node/node.exe ./Build/node_modules/jake/bin/cli.js -f ./Build/Scripts/Bootstrap.js $buildcmd
+    ./Build/Windows/node/node.exe ./Build/Scripts/Bootstrap.js buildeditor "$@"
 fi

+ 5 - 5
Script/AtomicNET/AtomicNET/Application/AppOptions.cs

@@ -73,10 +73,10 @@ namespace AtomicEngine
         public bool LimitFps { get; set; } = true;
 
 #if XFORMS
-		/// <summary>
-		/// iOS only
-		/// </summary>
-		public OrientationType Orientation { get; set; } = OrientationType.Portrait;
+        /// <summary>
+        /// iOS only
+        /// </summary>
+        public OrientationType Orientation { get; set; } = OrientationType.Portrait;
 #else
         /// <summary>
         /// iOS only
@@ -94,7 +94,7 @@ namespace AtomicEngine
         public string[] ResourcePackagesPaths { get; set; } = null;
 
 #if WINDOWS_UWP
-		public bool TouchEmulation { get { return true; } set {} }
+        public bool TouchEmulation { get { return true; } set {} }
 #else
         /// <summary>
         /// Touch emulation on desktop platform

+ 8 - 1
Script/AtomicNET/AtomicNET/Application/Application.cs

@@ -28,7 +28,14 @@ namespace AtomicEngine
             app = NETIPCPlayerApp.Create(args);
 #endif
 
-#if ATOMIC_ANDROID
+#if ATOMIC_IOS
+            // On iOS, we need to set main ready as main() isn't being called
+            SDLEvents.SetMainReady();
+#endif
+
+
+#if ATOMIC_ANDROID || ATOMIC_IOS
+
             app = NETAtomicPlayer.Create(args);
             
             var renderer = AtomicNET.GetSubsystem<Renderer>();

+ 6 - 7
Script/AtomicNET/AtomicNET/Core/AtomicNET.cs

@@ -46,6 +46,10 @@ namespace AtomicEngine
         [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
         private static extern uint csi_Atomic_AtomicNET_StringToStringHash(string name);
 
+        // static members so they don't get GC'd
+        private static EventDispatchDelegate eventDispatchDelegate = NativeCore.EventDispatch;
+        private static UpdateDispatchDelegate updateDispatchDelegate = NativeCore.UpdateDispatch;
+
         public static void Initialize()
         {
             // Atomic Modules
@@ -77,11 +81,7 @@ namespace AtomicEngine
 
             PlayerModule.Initialize();
 
-            coreDelegates = new CoreDelegates();
-            coreDelegates.eventDispatch = NativeCore.EventDispatch;
-            coreDelegates.updateDispatch = NativeCore.UpdateDispatch;
-
-            IntPtr coreptr = csi_Atomic_NETCore_Initialize(ref coreDelegates);
+            IntPtr coreptr = csi_Atomic_NETCore_Initialize(eventDispatchDelegate, updateDispatchDelegate);
 
             NETCore core = (coreptr == IntPtr.Zero ? null : NativeCore.WrapNative<NETCore>(coreptr));
 
@@ -102,10 +102,9 @@ namespace AtomicEngine
         }
 
         [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
-        private static extern IntPtr csi_Atomic_NETCore_Initialize(ref CoreDelegates delegates);
+        private static extern IntPtr csi_Atomic_NETCore_Initialize(EventDispatchDelegate eventDispatch, UpdateDispatchDelegate updateDispatch);
 
         private static Context context;
-        private static CoreDelegates coreDelegates;
         private static Dictionary<Type, AObject> subSystems = new Dictionary<Type, AObject>();
 
     }

+ 3 - 1
Script/AtomicNET/AtomicNET/Core/Constants.cs

@@ -4,7 +4,9 @@ namespace AtomicEngine
     public static partial class Constants
     {
 
-#if __MonoCS__
+#if ATOMIC_IOS
+        public const string LIBNAME = "@rpath/AtomicNETNative.framework/AtomicNETNative";
+#elif __MonoCS__
         public const string LIBNAME = "AtomicNETNative";
 #else
         public const string LIBNAME = "AtomicNETNative.dll";

+ 30 - 13
Script/AtomicNET/AtomicNET/Core/NativeCore.cs

@@ -5,9 +5,19 @@ using System.Runtime.InteropServices;
 using System.Linq;
 using static System.Reflection.IntrospectionExtensions;
 
+#if ATOMIC_IOS
+using ObjCRuntime;
+#endif
+
 namespace AtomicEngine
 {
 
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    public delegate void EventDispatchDelegate(IntPtr sender, uint eventType, IntPtr eventData);
+
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    public delegate void UpdateDispatchDelegate(float timeStep);
+
     public class NativeType
     {
 
@@ -124,6 +134,26 @@ namespace AtomicEngine
                 svm[i] = new ScriptVariantMap();
         }
 
+
+        static float expireDelta = 0.0f;
+
+        // called ahead of E_UPDATE event
+#if ATOMIC_IOS
+        [MonoPInvokeCallback(typeof(UpdateDispatchDelegate))]
+#endif
+        public static void UpdateDispatch(float timeStep)
+        {
+            expireDelta += timeStep;
+            if (expireDelta > 2.0f)
+            {
+                expireDelta = 0.0f;
+                ExpireNatives();
+            }
+        }
+
+        #if ATOMIC_IOS
+        [MonoPInvokeCallback(typeof(EventDispatchDelegate))]
+        #endif
         public static void EventDispatch(IntPtr sender, uint eventType, IntPtr eventData)
         {
             List<EventSubscription> eventReceivers;
@@ -240,19 +270,6 @@ namespace AtomicEngine
 
         }
 
-        static float expireDelta = 0.0f;
-
-        // called ahead of E_UPDATE event
-        public static void UpdateDispatch(float timeStep)
-        {
-            expireDelta += timeStep;
-            if (expireDelta > 2.0f)
-            {
-                expireDelta = 0.0f;
-                ExpireNatives();
-            }
-        }
-
         // register a newly created native
         public static IntPtr RegisterNative(IntPtr native, RefCounted r)
         {

+ 0 - 18
Script/AtomicNET/AtomicNET/Core/NativeEvents.cs

@@ -3,28 +3,10 @@ using System.Runtime.InteropServices;
 
 namespace AtomicEngine
 {
-    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-    public delegate void EventDispatchDelegate(IntPtr sender, uint eventType, IntPtr eventData);
-
-    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-    public delegate void UpdateDispatchDelegate(float timeStep);
-
     public delegate void EventDelegate(uint eventType, ScriptVariantMap eventData);
 
     public delegate void SenderEventDelegate(AObject sender, uint eventType, ScriptVariantMap eventData);
 
-    public delegate void HandleUpdateDelegate(float timeStep);
-
-    [StructLayout(LayoutKind.Sequential)]
-    public struct CoreDelegates
-    {
-        [MarshalAs(UnmanagedType.FunctionPtr)]
-        public EventDispatchDelegate eventDispatch;
-
-        [MarshalAs(UnmanagedType.FunctionPtr)]
-        public UpdateDispatchDelegate updateDispatch;
-    }
-
     public partial class ScriptVariantMap
     {
         public void CopyVariantMap(IntPtr vm)

+ 602 - 602
Script/AtomicNET/AtomicNET/Core/SDLConsts.cs

@@ -29,607 +29,607 @@
 namespace AtomicEngine
 {
 
-	public static class SDL
-	{
-
-
-		public const int SDL_BUTTON_LEFT =	1;
-		public const int SDL_BUTTON_MIDDLE =	2;
-		public const int SDL_BUTTON_RIGHT =	3;
-		public const int SDL_BUTTON_X1 =	4;
-		public const int SDL_BUTTON_X2 =	5;
-		public const int SDL_BUTTON_LMASK =	(1 << ((int)SDL_BUTTON_LEFT - 1));
-		public const int SDL_BUTTON_MMASK =	(1 << ((int)SDL_BUTTON_MIDDLE - 1));
-		public const int SDL_BUTTON_RMASK =	(1 << ((int)SDL_BUTTON_RIGHT - 1));
-		public const int SDL_BUTTON_X1MASK = (1 << ((int)SDL_BUTTON_X1 - 1));
-		public const int SDL_BUTTON_X2MASK = (1 << ((int)SDL_BUTTON_X2 - 1));
-
-		public const byte SDL_HAT_CENTERED =	0x00;
-		public const byte SDL_HAT_UP =		0x01;
-		public const byte SDL_HAT_RIGHT =	0x02;
-		public const byte SDL_HAT_DOWN =	0x04;
-		public const byte SDL_HAT_LEFT =	0x08;
-		public const byte SDL_HAT_RIGHTUP =	SDL_HAT_RIGHT | SDL_HAT_UP;
-		public const byte SDL_HAT_RIGHTDOWN =	SDL_HAT_RIGHT | SDL_HAT_DOWN;
-		public const byte SDL_HAT_LEFTUP =	SDL_HAT_LEFT | SDL_HAT_UP;
-		public const byte SDL_HAT_LEFTDOWN =	SDL_HAT_LEFT | SDL_HAT_DOWN;
-
-		public enum SDL_GameControllerButton
-		{
-			SDL_CONTROLLER_BUTTON_INVALID = -1,
-			SDL_CONTROLLER_BUTTON_A,
-			SDL_CONTROLLER_BUTTON_B,
-			SDL_CONTROLLER_BUTTON_X,
-			SDL_CONTROLLER_BUTTON_Y,
-			SDL_CONTROLLER_BUTTON_BACK,
-			SDL_CONTROLLER_BUTTON_GUIDE,
-			SDL_CONTROLLER_BUTTON_START,
-			SDL_CONTROLLER_BUTTON_LEFTSTICK,
-			SDL_CONTROLLER_BUTTON_RIGHTSTICK,
-			SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
-			SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
-			SDL_CONTROLLER_BUTTON_DPAD_UP,
-			SDL_CONTROLLER_BUTTON_DPAD_DOWN,
-			SDL_CONTROLLER_BUTTON_DPAD_LEFT,
-			SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
-			SDL_CONTROLLER_BUTTON_MAX,
-		}
-
-		public enum SDL_GameControllerAxis
-		{
-			SDL_CONTROLLER_AXIS_INVALID = -1,
-			SDL_CONTROLLER_AXIS_LEFTX,
-			SDL_CONTROLLER_AXIS_LEFTY,
-			SDL_CONTROLLER_AXIS_RIGHTX,
-			SDL_CONTROLLER_AXIS_RIGHTY,
-			SDL_CONTROLLER_AXIS_TRIGGERLEFT,
-			SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
-			SDL_CONTROLLER_AXIS_MAX
-		}
-
-
-		/* Scancodes based off USB keyboard page (0x07) */
-		public enum SDL_Scancode
-		{
-			SDL_SCANCODE_UNKNOWN = 0,
-
-			SDL_SCANCODE_A = 4,
-			SDL_SCANCODE_B = 5,
-			SDL_SCANCODE_C = 6,
-			SDL_SCANCODE_D = 7,
-			SDL_SCANCODE_E = 8,
-			SDL_SCANCODE_F = 9,
-			SDL_SCANCODE_G = 10,
-			SDL_SCANCODE_H = 11,
-			SDL_SCANCODE_I = 12,
-			SDL_SCANCODE_J = 13,
-			SDL_SCANCODE_K = 14,
-			SDL_SCANCODE_L = 15,
-			SDL_SCANCODE_M = 16,
-			SDL_SCANCODE_N = 17,
-			SDL_SCANCODE_O = 18,
-			SDL_SCANCODE_P = 19,
-			SDL_SCANCODE_Q = 20,
-			SDL_SCANCODE_R = 21,
-			SDL_SCANCODE_S = 22,
-			SDL_SCANCODE_T = 23,
-			SDL_SCANCODE_U = 24,
-			SDL_SCANCODE_V = 25,
-			SDL_SCANCODE_W = 26,
-			SDL_SCANCODE_X = 27,
-			SDL_SCANCODE_Y = 28,
-			SDL_SCANCODE_Z = 29,
-
-			SDL_SCANCODE_1 = 30,
-			SDL_SCANCODE_2 = 31,
-			SDL_SCANCODE_3 = 32,
-			SDL_SCANCODE_4 = 33,
-			SDL_SCANCODE_5 = 34,
-			SDL_SCANCODE_6 = 35,
-			SDL_SCANCODE_7 = 36,
-			SDL_SCANCODE_8 = 37,
-			SDL_SCANCODE_9 = 38,
-			SDL_SCANCODE_0 = 39,
-
-			SDL_SCANCODE_RETURN = 40,
-			SDL_SCANCODE_ESCAPE = 41,
-			SDL_SCANCODE_BACKSPACE = 42,
-			SDL_SCANCODE_TAB = 43,
-			SDL_SCANCODE_SPACE = 44,
-
-			SDL_SCANCODE_MINUS = 45,
-			SDL_SCANCODE_EQUALS = 46,
-			SDL_SCANCODE_LEFTBRACKET = 47,
-			SDL_SCANCODE_RIGHTBRACKET = 48,
-			SDL_SCANCODE_BACKSLASH = 49,
-			SDL_SCANCODE_NONUSHASH = 50,
-			SDL_SCANCODE_SEMICOLON = 51,
-			SDL_SCANCODE_APOSTROPHE = 52,
-			SDL_SCANCODE_GRAVE = 53,
-			SDL_SCANCODE_COMMA = 54,
-			SDL_SCANCODE_PERIOD = 55,
-			SDL_SCANCODE_SLASH = 56,
-
-			SDL_SCANCODE_CAPSLOCK = 57,
-
-			SDL_SCANCODE_F1 = 58,
-			SDL_SCANCODE_F2 = 59,
-			SDL_SCANCODE_F3 = 60,
-			SDL_SCANCODE_F4 = 61,
-			SDL_SCANCODE_F5 = 62,
-			SDL_SCANCODE_F6 = 63,
-			SDL_SCANCODE_F7 = 64,
-			SDL_SCANCODE_F8 = 65,
-			SDL_SCANCODE_F9 = 66,
-			SDL_SCANCODE_F10 = 67,
-			SDL_SCANCODE_F11 = 68,
-			SDL_SCANCODE_F12 = 69,
-
-			SDL_SCANCODE_PRINTSCREEN = 70,
-			SDL_SCANCODE_SCROLLLOCK = 71,
-			SDL_SCANCODE_PAUSE = 72,
-			SDL_SCANCODE_INSERT = 73,
-			SDL_SCANCODE_HOME = 74,
-			SDL_SCANCODE_PAGEUP = 75,
-			SDL_SCANCODE_DELETE = 76,
-			SDL_SCANCODE_END = 77,
-			SDL_SCANCODE_PAGEDOWN = 78,
-			SDL_SCANCODE_RIGHT = 79,
-			SDL_SCANCODE_LEFT = 80,
-			SDL_SCANCODE_DOWN = 81,
-			SDL_SCANCODE_UP = 82,
-
-			SDL_SCANCODE_NUMLOCKCLEAR = 83,
-			SDL_SCANCODE_KP_DIVIDE = 84,
-			SDL_SCANCODE_KP_MULTIPLY = 85,
-			SDL_SCANCODE_KP_MINUS = 86,
-			SDL_SCANCODE_KP_PLUS = 87,
-			SDL_SCANCODE_KP_ENTER = 88,
-			SDL_SCANCODE_KP_1 = 89,
-			SDL_SCANCODE_KP_2 = 90,
-			SDL_SCANCODE_KP_3 = 91,
-			SDL_SCANCODE_KP_4 = 92,
-			SDL_SCANCODE_KP_5 = 93,
-			SDL_SCANCODE_KP_6 = 94,
-			SDL_SCANCODE_KP_7 = 95,
-			SDL_SCANCODE_KP_8 = 96,
-			SDL_SCANCODE_KP_9 = 97,
-			SDL_SCANCODE_KP_0 = 98,
-			SDL_SCANCODE_KP_PERIOD = 99,
-
-			SDL_SCANCODE_NONUSBACKSLASH = 100,
-			SDL_SCANCODE_APPLICATION = 101,
-			SDL_SCANCODE_POWER = 102,
-			SDL_SCANCODE_KP_EQUALS = 103,
-			SDL_SCANCODE_F13 = 104,
-			SDL_SCANCODE_F14 = 105,
-			SDL_SCANCODE_F15 = 106,
-			SDL_SCANCODE_F16 = 107,
-			SDL_SCANCODE_F17 = 108,
-			SDL_SCANCODE_F18 = 109,
-			SDL_SCANCODE_F19 = 110,
-			SDL_SCANCODE_F20 = 111,
-			SDL_SCANCODE_F21 = 112,
-			SDL_SCANCODE_F22 = 113,
-			SDL_SCANCODE_F23 = 114,
-			SDL_SCANCODE_F24 = 115,
-			SDL_SCANCODE_EXECUTE = 116,
-			SDL_SCANCODE_HELP = 117,
-			SDL_SCANCODE_MENU = 118,
-			SDL_SCANCODE_SELECT = 119,
-			SDL_SCANCODE_STOP = 120,
-			SDL_SCANCODE_AGAIN = 121,
-			SDL_SCANCODE_UNDO = 122,
-			SDL_SCANCODE_CUT = 123,
-			SDL_SCANCODE_COPY = 124,
-			SDL_SCANCODE_PASTE = 125,
-			SDL_SCANCODE_FIND = 126,
-			SDL_SCANCODE_MUTE = 127,
-			SDL_SCANCODE_VOLUMEUP = 128,
-			SDL_SCANCODE_VOLUMEDOWN = 129,
-			/* not sure whether there's a reason to enable these */
-			/*	SDL_SCANCODE_LOCKINGCAPSLOCK = 130,  */
-			/*	SDL_SCANCODE_LOCKINGNUMLOCK = 131, */
-			/*	SDL_SCANCODE_LOCKINGSCROLLLOCK = 132, */
-			SDL_SCANCODE_KP_COMMA = 133,
-			SDL_SCANCODE_KP_EQUALSAS400 = 134,
-
-			SDL_SCANCODE_INTERNATIONAL1 = 135,
-			SDL_SCANCODE_INTERNATIONAL2 = 136,
-			SDL_SCANCODE_INTERNATIONAL3 = 137,
-			SDL_SCANCODE_INTERNATIONAL4 = 138,
-			SDL_SCANCODE_INTERNATIONAL5 = 139,
-			SDL_SCANCODE_INTERNATIONAL6 = 140,
-			SDL_SCANCODE_INTERNATIONAL7 = 141,
-			SDL_SCANCODE_INTERNATIONAL8 = 142,
-			SDL_SCANCODE_INTERNATIONAL9 = 143,
-			SDL_SCANCODE_LANG1 = 144,
-			SDL_SCANCODE_LANG2 = 145,
-			SDL_SCANCODE_LANG3 = 146,
-			SDL_SCANCODE_LANG4 = 147,
-			SDL_SCANCODE_LANG5 = 148,
-			SDL_SCANCODE_LANG6 = 149,
-			SDL_SCANCODE_LANG7 = 150,
-			SDL_SCANCODE_LANG8 = 151,
-			SDL_SCANCODE_LANG9 = 152,
-
-			SDL_SCANCODE_ALTERASE = 153,
-			SDL_SCANCODE_SYSREQ = 154,
-			SDL_SCANCODE_CANCEL = 155,
-			SDL_SCANCODE_CLEAR = 156,
-			SDL_SCANCODE_PRIOR = 157,
-			SDL_SCANCODE_RETURN2 = 158,
-			SDL_SCANCODE_SEPARATOR = 159,
-			SDL_SCANCODE_OUT = 160,
-			SDL_SCANCODE_OPER = 161,
-			SDL_SCANCODE_CLEARAGAIN = 162,
-			SDL_SCANCODE_CRSEL = 163,
-			SDL_SCANCODE_EXSEL = 164,
-
-			SDL_SCANCODE_KP_00 = 176,
-			SDL_SCANCODE_KP_000 = 177,
-			SDL_SCANCODE_THOUSANDSSEPARATOR = 178,
-			SDL_SCANCODE_DECIMALSEPARATOR = 179,
-			SDL_SCANCODE_CURRENCYUNIT = 180,
-			SDL_SCANCODE_CURRENCYSUBUNIT = 181,
-			SDL_SCANCODE_KP_LEFTPAREN = 182,
-			SDL_SCANCODE_KP_RIGHTPAREN = 183,
-			SDL_SCANCODE_KP_LEFTBRACE = 184,
-			SDL_SCANCODE_KP_RIGHTBRACE = 185,
-			SDL_SCANCODE_KP_TAB = 186,
-			SDL_SCANCODE_KP_BACKSPACE = 187,
-			SDL_SCANCODE_KP_A = 188,
-			SDL_SCANCODE_KP_B = 189,
-			SDL_SCANCODE_KP_C = 190,
-			SDL_SCANCODE_KP_D = 191,
-			SDL_SCANCODE_KP_E = 192,
-			SDL_SCANCODE_KP_F = 193,
-			SDL_SCANCODE_KP_XOR = 194,
-			SDL_SCANCODE_KP_POWER = 195,
-			SDL_SCANCODE_KP_PERCENT = 196,
-			SDL_SCANCODE_KP_LESS = 197,
-			SDL_SCANCODE_KP_GREATER = 198,
-			SDL_SCANCODE_KP_AMPERSAND = 199,
-			SDL_SCANCODE_KP_DBLAMPERSAND = 200,
-			SDL_SCANCODE_KP_VERTICALBAR = 201,
-			SDL_SCANCODE_KP_DBLVERTICALBAR = 202,
-			SDL_SCANCODE_KP_COLON = 203,
-			SDL_SCANCODE_KP_HASH = 204,
-			SDL_SCANCODE_KP_SPACE = 205,
-			SDL_SCANCODE_KP_AT = 206,
-			SDL_SCANCODE_KP_EXCLAM = 207,
-			SDL_SCANCODE_KP_MEMSTORE = 208,
-			SDL_SCANCODE_KP_MEMRECALL = 209,
-			SDL_SCANCODE_KP_MEMCLEAR = 210,
-			SDL_SCANCODE_KP_MEMADD = 211,
-			SDL_SCANCODE_KP_MEMSUBTRACT = 212,
-			SDL_SCANCODE_KP_MEMMULTIPLY = 213,
-			SDL_SCANCODE_KP_MEMDIVIDE = 214,
-			SDL_SCANCODE_KP_PLUSMINUS = 215,
-			SDL_SCANCODE_KP_CLEAR = 216,
-			SDL_SCANCODE_KP_CLEARENTRY = 217,
-			SDL_SCANCODE_KP_BINARY = 218,
-			SDL_SCANCODE_KP_OCTAL = 219,
-			SDL_SCANCODE_KP_DECIMAL = 220,
-			SDL_SCANCODE_KP_HEXADECIMAL = 221,
-
-			SDL_SCANCODE_LCTRL = 224,
-			SDL_SCANCODE_LSHIFT = 225,
-			SDL_SCANCODE_LALT = 226,
-			SDL_SCANCODE_LGUI = 227,
-			SDL_SCANCODE_RCTRL = 228,
-			SDL_SCANCODE_RSHIFT = 229,
-			SDL_SCANCODE_RALT = 230,
-			SDL_SCANCODE_RGUI = 231,
-
-			SDL_SCANCODE_MODE = 257,
-
-			/* These come from the USB consumer page (0x0C) */
-			SDL_SCANCODE_AUDIONEXT = 258,
-			SDL_SCANCODE_AUDIOPREV = 259,
-			SDL_SCANCODE_AUDIOSTOP = 260,
-			SDL_SCANCODE_AUDIOPLAY = 261,
-			SDL_SCANCODE_AUDIOMUTE = 262,
-			SDL_SCANCODE_MEDIASELECT = 263,
-			SDL_SCANCODE_WWW = 264,
-			SDL_SCANCODE_MAIL = 265,
-			SDL_SCANCODE_CALCULATOR = 266,
-			SDL_SCANCODE_COMPUTER = 267,
-			SDL_SCANCODE_AC_SEARCH = 268,
-			SDL_SCANCODE_AC_HOME = 269,
-			SDL_SCANCODE_AC_BACK = 270,
-			SDL_SCANCODE_AC_FORWARD = 271,
-			SDL_SCANCODE_AC_STOP = 272,
-			SDL_SCANCODE_AC_REFRESH = 273,
-			SDL_SCANCODE_AC_BOOKMARKS = 274,
-
-			/* These come from other sources, and are mostly mac related */
-			SDL_SCANCODE_BRIGHTNESSDOWN = 275,
-			SDL_SCANCODE_BRIGHTNESSUP = 276,
-			SDL_SCANCODE_DISPLAYSWITCH = 277,
-			SDL_SCANCODE_KBDILLUMTOGGLE = 278,
-			SDL_SCANCODE_KBDILLUMDOWN = 279,
-			SDL_SCANCODE_KBDILLUMUP = 280,
-			SDL_SCANCODE_EJECT = 281,
-			SDL_SCANCODE_SLEEP = 282,
-
-			SDL_SCANCODE_APP1 = 283,
-			SDL_SCANCODE_APP2 = 284,
-
-			/* This is not a key, simply marks the number of scancodes
-			 * so that you know how big to make your arrays. */
-			SDL_NUM_SCANCODES = 512
-		}
-
-		public const int SDLK_SCANCODE_MASK = (1 << 30);
-
-		public enum SDL_Keycode
-		{
-			SDLK_UNKNOWN = 0,
-
-			SDLK_RETURN = '\r',
-			SDLK_ESCAPE = 27,
-			// '\033'
-			SDLK_BACKSPACE = '\b',
-			SDLK_TAB = '\t',
-			SDLK_SPACE = ' ',
-			SDLK_EXCLAIM = '!',
-			SDLK_QUOTEDBL = '"',
-			SDLK_HASH = '#',
-			SDLK_PERCENT = '%',
-			SDLK_DOLLAR = '$',
-			SDLK_AMPERSAND = '&',
-			SDLK_QUOTE = '\'',
-			SDLK_LEFTPAREN = '(',
-			SDLK_RIGHTPAREN = ')',
-			SDLK_ASTERISK = '*',
-			SDLK_PLUS = '+',
-			SDLK_COMMA = ',',
-			SDLK_MINUS = '-',
-			SDLK_PERIOD = '.',
-			SDLK_SLASH = '/',
-			SDLK_0 = '0',
-			SDLK_1 = '1',
-			SDLK_2 = '2',
-			SDLK_3 = '3',
-			SDLK_4 = '4',
-			SDLK_5 = '5',
-			SDLK_6 = '6',
-			SDLK_7 = '7',
-			SDLK_8 = '8',
-			SDLK_9 = '9',
-			SDLK_COLON = ':',
-			SDLK_SEMICOLON = ';',
-			SDLK_LESS = '<',
-			SDLK_EQUALS = '=',
-			SDLK_GREATER = '>',
-			SDLK_QUESTION = '?',
-			SDLK_AT = '@',
-			/*
-			Skip uppercase letters
-			*/
-			SDLK_LEFTBRACKET = '[',
-			SDLK_BACKSLASH = '\\',
-			SDLK_RIGHTBRACKET = ']',
-			SDLK_CARET = '^',
-			SDLK_UNDERSCORE = '_',
-			SDLK_BACKQUOTE = '`',
-			SDLK_a = 'a',
-			SDLK_b = 'b',
-			SDLK_c = 'c',
-			SDLK_d = 'd',
-			SDLK_e = 'e',
-			SDLK_f = 'f',
-			SDLK_g = 'g',
-			SDLK_h = 'h',
-			SDLK_i = 'i',
-			SDLK_j = 'j',
-			SDLK_k = 'k',
-			SDLK_l = 'l',
-			SDLK_m = 'm',
-			SDLK_n = 'n',
-			SDLK_o = 'o',
-			SDLK_p = 'p',
-			SDLK_q = 'q',
-			SDLK_r = 'r',
-			SDLK_s = 's',
-			SDLK_t = 't',
-			SDLK_u = 'u',
-			SDLK_v = 'v',
-			SDLK_w = 'w',
-			SDLK_x = 'x',
-			SDLK_y = 'y',
-			SDLK_z = 'z',
-
-			SDLK_CAPSLOCK = (int)SDL_Scancode.SDL_SCANCODE_CAPSLOCK | SDLK_SCANCODE_MASK,
-
-			SDLK_F1 = (int)SDL_Scancode.SDL_SCANCODE_F1 | SDLK_SCANCODE_MASK,
-			SDLK_F2 = (int)SDL_Scancode.SDL_SCANCODE_F2 | SDLK_SCANCODE_MASK,
-			SDLK_F3 = (int)SDL_Scancode.SDL_SCANCODE_F3 | SDLK_SCANCODE_MASK,
-			SDLK_F4 = (int)SDL_Scancode.SDL_SCANCODE_F4 | SDLK_SCANCODE_MASK,
-			SDLK_F5 = (int)SDL_Scancode.SDL_SCANCODE_F5 | SDLK_SCANCODE_MASK,
-			SDLK_F6 = (int)SDL_Scancode.SDL_SCANCODE_F6 | SDLK_SCANCODE_MASK,
-			SDLK_F7 = (int)SDL_Scancode.SDL_SCANCODE_F7 | SDLK_SCANCODE_MASK,
-			SDLK_F8 = (int)SDL_Scancode.SDL_SCANCODE_F8 | SDLK_SCANCODE_MASK,
-			SDLK_F9 = (int)SDL_Scancode.SDL_SCANCODE_F9 | SDLK_SCANCODE_MASK,
-			SDLK_F10 = (int)SDL_Scancode.SDL_SCANCODE_F10 | SDLK_SCANCODE_MASK,
-			SDLK_F11 = (int)SDL_Scancode.SDL_SCANCODE_F11 | SDLK_SCANCODE_MASK,
-			SDLK_F12 = (int)SDL_Scancode.SDL_SCANCODE_F12 | SDLK_SCANCODE_MASK,
-
-			SDLK_PRINTSCREEN = (int)SDL_Scancode.SDL_SCANCODE_PRINTSCREEN | SDLK_SCANCODE_MASK,
-			SDLK_SCROLLLOCK = (int)SDL_Scancode.SDL_SCANCODE_SCROLLLOCK | SDLK_SCANCODE_MASK,
-			SDLK_PAUSE = (int)SDL_Scancode.SDL_SCANCODE_PAUSE | SDLK_SCANCODE_MASK,
-			SDLK_INSERT = (int)SDL_Scancode.SDL_SCANCODE_INSERT | SDLK_SCANCODE_MASK,
-			SDLK_HOME = (int)SDL_Scancode.SDL_SCANCODE_HOME | SDLK_SCANCODE_MASK,
-			SDLK_PAGEUP = (int)SDL_Scancode.SDL_SCANCODE_PAGEUP | SDLK_SCANCODE_MASK,
-			SDLK_DELETE = 127,
-			SDLK_END = (int)SDL_Scancode.SDL_SCANCODE_END | SDLK_SCANCODE_MASK,
-			SDLK_PAGEDOWN = (int)SDL_Scancode.SDL_SCANCODE_PAGEDOWN | SDLK_SCANCODE_MASK,
-			SDLK_RIGHT = (int)SDL_Scancode.SDL_SCANCODE_RIGHT | SDLK_SCANCODE_MASK,
-			SDLK_LEFT = (int)SDL_Scancode.SDL_SCANCODE_LEFT | SDLK_SCANCODE_MASK,
-			SDLK_DOWN = (int)SDL_Scancode.SDL_SCANCODE_DOWN | SDLK_SCANCODE_MASK,
-			SDLK_UP = (int)SDL_Scancode.SDL_SCANCODE_UP | SDLK_SCANCODE_MASK,
-
-			SDLK_NUMLOCKCLEAR = (int)SDL_Scancode.SDL_SCANCODE_NUMLOCKCLEAR | SDLK_SCANCODE_MASK,
-			SDLK_KP_DIVIDE = (int)SDL_Scancode.SDL_SCANCODE_KP_DIVIDE | SDLK_SCANCODE_MASK,
-			SDLK_KP_MULTIPLY = (int)SDL_Scancode.SDL_SCANCODE_KP_MULTIPLY | SDLK_SCANCODE_MASK,
-			SDLK_KP_MINUS = (int)SDL_Scancode.SDL_SCANCODE_KP_MINUS | SDLK_SCANCODE_MASK,
-			SDLK_KP_PLUS = (int)SDL_Scancode.SDL_SCANCODE_KP_PLUS | SDLK_SCANCODE_MASK,
-			SDLK_KP_ENTER = (int)SDL_Scancode.SDL_SCANCODE_KP_ENTER | SDLK_SCANCODE_MASK,
-			SDLK_KP_1 = (int)SDL_Scancode.SDL_SCANCODE_KP_1 | SDLK_SCANCODE_MASK,
-			SDLK_KP_2 = (int)SDL_Scancode.SDL_SCANCODE_KP_2 | SDLK_SCANCODE_MASK,
-			SDLK_KP_3 = (int)SDL_Scancode.SDL_SCANCODE_KP_3 | SDLK_SCANCODE_MASK,
-			SDLK_KP_4 = (int)SDL_Scancode.SDL_SCANCODE_KP_4 | SDLK_SCANCODE_MASK,
-			SDLK_KP_5 = (int)SDL_Scancode.SDL_SCANCODE_KP_5 | SDLK_SCANCODE_MASK,
-			SDLK_KP_6 = (int)SDL_Scancode.SDL_SCANCODE_KP_6 | SDLK_SCANCODE_MASK,
-			SDLK_KP_7 = (int)SDL_Scancode.SDL_SCANCODE_KP_7 | SDLK_SCANCODE_MASK,
-			SDLK_KP_8 = (int)SDL_Scancode.SDL_SCANCODE_KP_8 | SDLK_SCANCODE_MASK,
-			SDLK_KP_9 = (int)SDL_Scancode.SDL_SCANCODE_KP_9 | SDLK_SCANCODE_MASK,
-			SDLK_KP_0 = (int)SDL_Scancode.SDL_SCANCODE_KP_0 | SDLK_SCANCODE_MASK,
-			SDLK_KP_PERIOD = (int)SDL_Scancode.SDL_SCANCODE_KP_PERIOD | SDLK_SCANCODE_MASK,
-
-			SDLK_APPLICATION = (int)SDL_Scancode.SDL_SCANCODE_APPLICATION | SDLK_SCANCODE_MASK,
-			SDLK_POWER = (int)SDL_Scancode.SDL_SCANCODE_POWER | SDLK_SCANCODE_MASK,
-			SDLK_KP_EQUALS = (int)SDL_Scancode.SDL_SCANCODE_KP_EQUALS | SDLK_SCANCODE_MASK,
-			SDLK_F13 = (int)SDL_Scancode.SDL_SCANCODE_F13 | SDLK_SCANCODE_MASK,
-			SDLK_F14 = (int)SDL_Scancode.SDL_SCANCODE_F14 | SDLK_SCANCODE_MASK,
-			SDLK_F15 = (int)SDL_Scancode.SDL_SCANCODE_F15 | SDLK_SCANCODE_MASK,
-			SDLK_F16 = (int)SDL_Scancode.SDL_SCANCODE_F16 | SDLK_SCANCODE_MASK,
-			SDLK_F17 = (int)SDL_Scancode.SDL_SCANCODE_F17 | SDLK_SCANCODE_MASK,
-			SDLK_F18 = (int)SDL_Scancode.SDL_SCANCODE_F18 | SDLK_SCANCODE_MASK,
-			SDLK_F19 = (int)SDL_Scancode.SDL_SCANCODE_F19 | SDLK_SCANCODE_MASK,
-			SDLK_F20 = (int)SDL_Scancode.SDL_SCANCODE_F20 | SDLK_SCANCODE_MASK,
-			SDLK_F21 = (int)SDL_Scancode.SDL_SCANCODE_F21 | SDLK_SCANCODE_MASK,
-			SDLK_F22 = (int)SDL_Scancode.SDL_SCANCODE_F22 | SDLK_SCANCODE_MASK,
-			SDLK_F23 = (int)SDL_Scancode.SDL_SCANCODE_F23 | SDLK_SCANCODE_MASK,
-			SDLK_F24 = (int)SDL_Scancode.SDL_SCANCODE_F24 | SDLK_SCANCODE_MASK,
-			SDLK_EXECUTE = (int)SDL_Scancode.SDL_SCANCODE_EXECUTE | SDLK_SCANCODE_MASK,
-			SDLK_HELP = (int)SDL_Scancode.SDL_SCANCODE_HELP | SDLK_SCANCODE_MASK,
-			SDLK_MENU = (int)SDL_Scancode.SDL_SCANCODE_MENU | SDLK_SCANCODE_MASK,
-			SDLK_SELECT = (int)SDL_Scancode.SDL_SCANCODE_SELECT | SDLK_SCANCODE_MASK,
-			SDLK_STOP = (int)SDL_Scancode.SDL_SCANCODE_STOP | SDLK_SCANCODE_MASK,
-			SDLK_AGAIN = (int)SDL_Scancode.SDL_SCANCODE_AGAIN | SDLK_SCANCODE_MASK,
-			SDLK_UNDO = (int)SDL_Scancode.SDL_SCANCODE_UNDO | SDLK_SCANCODE_MASK,
-			SDLK_CUT = (int)SDL_Scancode.SDL_SCANCODE_CUT | SDLK_SCANCODE_MASK,
-			SDLK_COPY = (int)SDL_Scancode.SDL_SCANCODE_COPY | SDLK_SCANCODE_MASK,
-			SDLK_PASTE = (int)SDL_Scancode.SDL_SCANCODE_PASTE | SDLK_SCANCODE_MASK,
-			SDLK_FIND = (int)SDL_Scancode.SDL_SCANCODE_FIND | SDLK_SCANCODE_MASK,
-			SDLK_MUTE = (int)SDL_Scancode.SDL_SCANCODE_MUTE | SDLK_SCANCODE_MASK,
-			SDLK_VOLUMEUP = (int)SDL_Scancode.SDL_SCANCODE_VOLUMEUP | SDLK_SCANCODE_MASK,
-			SDLK_VOLUMEDOWN = (int)SDL_Scancode.SDL_SCANCODE_VOLUMEDOWN | SDLK_SCANCODE_MASK,
-			SDLK_KP_COMMA = (int)SDL_Scancode.SDL_SCANCODE_KP_COMMA | SDLK_SCANCODE_MASK,
-			SDLK_KP_EQUALSAS400 =
-			(int)SDL_Scancode.SDL_SCANCODE_KP_EQUALSAS400 | SDLK_SCANCODE_MASK,
-
-			SDLK_ALTERASE = (int)SDL_Scancode.SDL_SCANCODE_ALTERASE | SDLK_SCANCODE_MASK,
-			SDLK_SYSREQ = (int)SDL_Scancode.SDL_SCANCODE_SYSREQ | SDLK_SCANCODE_MASK,
-			SDLK_CANCEL = (int)SDL_Scancode.SDL_SCANCODE_CANCEL | SDLK_SCANCODE_MASK,
-			SDLK_CLEAR = (int)SDL_Scancode.SDL_SCANCODE_CLEAR | SDLK_SCANCODE_MASK,
-			SDLK_PRIOR = (int)SDL_Scancode.SDL_SCANCODE_PRIOR | SDLK_SCANCODE_MASK,
-			SDLK_RETURN2 = (int)SDL_Scancode.SDL_SCANCODE_RETURN2 | SDLK_SCANCODE_MASK,
-			SDLK_SEPARATOR = (int)SDL_Scancode.SDL_SCANCODE_SEPARATOR | SDLK_SCANCODE_MASK,
-			SDLK_OUT = (int)SDL_Scancode.SDL_SCANCODE_OUT | SDLK_SCANCODE_MASK,
-			SDLK_OPER = (int)SDL_Scancode.SDL_SCANCODE_OPER | SDLK_SCANCODE_MASK,
-			SDLK_CLEARAGAIN = (int)SDL_Scancode.SDL_SCANCODE_CLEARAGAIN | SDLK_SCANCODE_MASK,
-			SDLK_CRSEL = (int)SDL_Scancode.SDL_SCANCODE_CRSEL | SDLK_SCANCODE_MASK,
-			SDLK_EXSEL = (int)SDL_Scancode.SDL_SCANCODE_EXSEL | SDLK_SCANCODE_MASK,
-
-			SDLK_KP_00 = (int)SDL_Scancode.SDL_SCANCODE_KP_00 | SDLK_SCANCODE_MASK,
-			SDLK_KP_000 = (int)SDL_Scancode.SDL_SCANCODE_KP_000 | SDLK_SCANCODE_MASK,
-			SDLK_THOUSANDSSEPARATOR =
-			(int)SDL_Scancode.SDL_SCANCODE_THOUSANDSSEPARATOR | SDLK_SCANCODE_MASK,
-			SDLK_DECIMALSEPARATOR =
-			(int)SDL_Scancode.SDL_SCANCODE_DECIMALSEPARATOR | SDLK_SCANCODE_MASK,
-			SDLK_CURRENCYUNIT = (int)SDL_Scancode.SDL_SCANCODE_CURRENCYUNIT | SDLK_SCANCODE_MASK,
-			SDLK_CURRENCYSUBUNIT =
-			(int)SDL_Scancode.SDL_SCANCODE_CURRENCYSUBUNIT | SDLK_SCANCODE_MASK,
-			SDLK_KP_LEFTPAREN = (int)SDL_Scancode.SDL_SCANCODE_KP_LEFTPAREN | SDLK_SCANCODE_MASK,
-			SDLK_KP_RIGHTPAREN = (int)SDL_Scancode.SDL_SCANCODE_KP_RIGHTPAREN | SDLK_SCANCODE_MASK,
-			SDLK_KP_LEFTBRACE = (int)SDL_Scancode.SDL_SCANCODE_KP_LEFTBRACE | SDLK_SCANCODE_MASK,
-			SDLK_KP_RIGHTBRACE = (int)SDL_Scancode.SDL_SCANCODE_KP_RIGHTBRACE | SDLK_SCANCODE_MASK,
-			SDLK_KP_TAB = (int)SDL_Scancode.SDL_SCANCODE_KP_TAB | SDLK_SCANCODE_MASK,
-			SDLK_KP_BACKSPACE = (int)SDL_Scancode.SDL_SCANCODE_KP_BACKSPACE | SDLK_SCANCODE_MASK,
-			SDLK_KP_A = (int)SDL_Scancode.SDL_SCANCODE_KP_A | SDLK_SCANCODE_MASK,
-			SDLK_KP_B = (int)SDL_Scancode.SDL_SCANCODE_KP_B | SDLK_SCANCODE_MASK,
-			SDLK_KP_C = (int)SDL_Scancode.SDL_SCANCODE_KP_C | SDLK_SCANCODE_MASK,
-			SDLK_KP_D = (int)SDL_Scancode.SDL_SCANCODE_KP_D | SDLK_SCANCODE_MASK,
-			SDLK_KP_E = (int)SDL_Scancode.SDL_SCANCODE_KP_E | SDLK_SCANCODE_MASK,
-			SDLK_KP_F = (int)SDL_Scancode.SDL_SCANCODE_KP_F | SDLK_SCANCODE_MASK,
-			SDLK_KP_XOR = (int)SDL_Scancode.SDL_SCANCODE_KP_XOR | SDLK_SCANCODE_MASK,
-			SDLK_KP_POWER = (int)SDL_Scancode.SDL_SCANCODE_KP_POWER | SDLK_SCANCODE_MASK,
-			SDLK_KP_PERCENT = (int)SDL_Scancode.SDL_SCANCODE_KP_PERCENT | SDLK_SCANCODE_MASK,
-			SDLK_KP_LESS = (int)SDL_Scancode.SDL_SCANCODE_KP_LESS | SDLK_SCANCODE_MASK,
-			SDLK_KP_GREATER = (int)SDL_Scancode.SDL_SCANCODE_KP_GREATER | SDLK_SCANCODE_MASK,
-			SDLK_KP_AMPERSAND = (int)SDL_Scancode.SDL_SCANCODE_KP_AMPERSAND | SDLK_SCANCODE_MASK,
-			SDLK_KP_DBLAMPERSAND =
-			(int)SDL_Scancode.SDL_SCANCODE_KP_DBLAMPERSAND | SDLK_SCANCODE_MASK,
-			SDLK_KP_VERTICALBAR =
-			(int)SDL_Scancode.SDL_SCANCODE_KP_VERTICALBAR | SDLK_SCANCODE_MASK,
-			SDLK_KP_DBLVERTICALBAR =
-			(int)SDL_Scancode.SDL_SCANCODE_KP_DBLVERTICALBAR | SDLK_SCANCODE_MASK,
-			SDLK_KP_COLON = (int)SDL_Scancode.SDL_SCANCODE_KP_COLON | SDLK_SCANCODE_MASK,
-			SDLK_KP_HASH = (int)SDL_Scancode.SDL_SCANCODE_KP_HASH | SDLK_SCANCODE_MASK,
-			SDLK_KP_SPACE = (int)SDL_Scancode.SDL_SCANCODE_KP_SPACE | SDLK_SCANCODE_MASK,
-			SDLK_KP_AT = (int)SDL_Scancode.SDL_SCANCODE_KP_AT | SDLK_SCANCODE_MASK,
-			SDLK_KP_EXCLAM = (int)SDL_Scancode.SDL_SCANCODE_KP_EXCLAM | SDLK_SCANCODE_MASK,
-			SDLK_KP_MEMSTORE = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMSTORE | SDLK_SCANCODE_MASK,
-			SDLK_KP_MEMRECALL = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMRECALL | SDLK_SCANCODE_MASK,
-			SDLK_KP_MEMCLEAR = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMCLEAR | SDLK_SCANCODE_MASK,
-			SDLK_KP_MEMADD = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMADD | SDLK_SCANCODE_MASK,
-			SDLK_KP_MEMSUBTRACT =
-			(int)SDL_Scancode.SDL_SCANCODE_KP_MEMSUBTRACT | SDLK_SCANCODE_MASK,
-			SDLK_KP_MEMMULTIPLY =
-			(int)SDL_Scancode.SDL_SCANCODE_KP_MEMMULTIPLY | SDLK_SCANCODE_MASK,
-			SDLK_KP_MEMDIVIDE = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMDIVIDE | SDLK_SCANCODE_MASK,
-			SDLK_KP_PLUSMINUS = (int)SDL_Scancode.SDL_SCANCODE_KP_PLUSMINUS | SDLK_SCANCODE_MASK,
-			SDLK_KP_CLEAR = (int)SDL_Scancode.SDL_SCANCODE_KP_CLEAR | SDLK_SCANCODE_MASK,
-			SDLK_KP_CLEARENTRY = (int)SDL_Scancode.SDL_SCANCODE_KP_CLEARENTRY | SDLK_SCANCODE_MASK,
-			SDLK_KP_BINARY = (int)SDL_Scancode.SDL_SCANCODE_KP_BINARY | SDLK_SCANCODE_MASK,
-			SDLK_KP_OCTAL = (int)SDL_Scancode.SDL_SCANCODE_KP_OCTAL | SDLK_SCANCODE_MASK,
-			SDLK_KP_DECIMAL = (int)SDL_Scancode.SDL_SCANCODE_KP_DECIMAL | SDLK_SCANCODE_MASK,
-			SDLK_KP_HEXADECIMAL =
-			(int)SDL_Scancode.SDL_SCANCODE_KP_HEXADECIMAL | SDLK_SCANCODE_MASK,
-
-			SDLK_LCTRL = (int)SDL_Scancode.SDL_SCANCODE_LCTRL | SDLK_SCANCODE_MASK,
-			SDLK_LSHIFT = (int)SDL_Scancode.SDL_SCANCODE_LSHIFT | SDLK_SCANCODE_MASK,
-			SDLK_LALT = (int)SDL_Scancode.SDL_SCANCODE_LALT | SDLK_SCANCODE_MASK,
-			SDLK_LGUI = (int)SDL_Scancode.SDL_SCANCODE_LGUI | SDLK_SCANCODE_MASK,
-			SDLK_RCTRL = (int)SDL_Scancode.SDL_SCANCODE_RCTRL | SDLK_SCANCODE_MASK,
-			SDLK_RSHIFT = (int)SDL_Scancode.SDL_SCANCODE_RSHIFT | SDLK_SCANCODE_MASK,
-			SDLK_RALT = (int)SDL_Scancode.SDL_SCANCODE_RALT | SDLK_SCANCODE_MASK,
-			SDLK_RGUI = (int)SDL_Scancode.SDL_SCANCODE_RGUI | SDLK_SCANCODE_MASK,
-
-			SDLK_MODE = (int)SDL_Scancode.SDL_SCANCODE_MODE | SDLK_SCANCODE_MASK,
-
-			SDLK_AUDIONEXT = (int)SDL_Scancode.SDL_SCANCODE_AUDIONEXT | SDLK_SCANCODE_MASK,
-			SDLK_AUDIOPREV = (int)SDL_Scancode.SDL_SCANCODE_AUDIOPREV | SDLK_SCANCODE_MASK,
-			SDLK_AUDIOSTOP = (int)SDL_Scancode.SDL_SCANCODE_AUDIOSTOP | SDLK_SCANCODE_MASK,
-			SDLK_AUDIOPLAY = (int)SDL_Scancode.SDL_SCANCODE_AUDIOPLAY | SDLK_SCANCODE_MASK,
-			SDLK_AUDIOMUTE = (int)SDL_Scancode.SDL_SCANCODE_AUDIOMUTE | SDLK_SCANCODE_MASK,
-			SDLK_MEDIASELECT = (int)SDL_Scancode.SDL_SCANCODE_MEDIASELECT | SDLK_SCANCODE_MASK,
-			SDLK_WWW = (int)SDL_Scancode.SDL_SCANCODE_WWW | SDLK_SCANCODE_MASK,
-			SDLK_MAIL = (int)SDL_Scancode.SDL_SCANCODE_MAIL | SDLK_SCANCODE_MASK,
-			SDLK_CALCULATOR = (int)SDL_Scancode.SDL_SCANCODE_CALCULATOR | SDLK_SCANCODE_MASK,
-			SDLK_COMPUTER = (int)SDL_Scancode.SDL_SCANCODE_COMPUTER | SDLK_SCANCODE_MASK,
-			SDLK_AC_SEARCH = (int)SDL_Scancode.SDL_SCANCODE_AC_SEARCH | SDLK_SCANCODE_MASK,
-			SDLK_AC_HOME = (int)SDL_Scancode.SDL_SCANCODE_AC_HOME | SDLK_SCANCODE_MASK,
-			SDLK_AC_BACK = (int)SDL_Scancode.SDL_SCANCODE_AC_BACK | SDLK_SCANCODE_MASK,
-			SDLK_AC_FORWARD = (int)SDL_Scancode.SDL_SCANCODE_AC_FORWARD | SDLK_SCANCODE_MASK,
-			SDLK_AC_STOP = (int)SDL_Scancode.SDL_SCANCODE_AC_STOP | SDLK_SCANCODE_MASK,
-			SDLK_AC_REFRESH = (int)SDL_Scancode.SDL_SCANCODE_AC_REFRESH | SDLK_SCANCODE_MASK,
-			SDLK_AC_BOOKMARKS = (int)SDL_Scancode.SDL_SCANCODE_AC_BOOKMARKS | SDLK_SCANCODE_MASK,
-
-			SDLK_BRIGHTNESSDOWN =
-			(int)SDL_Scancode.SDL_SCANCODE_BRIGHTNESSDOWN | SDLK_SCANCODE_MASK,
-			SDLK_BRIGHTNESSUP = (int)SDL_Scancode.SDL_SCANCODE_BRIGHTNESSUP | SDLK_SCANCODE_MASK,
-			SDLK_DISPLAYSWITCH = (int)SDL_Scancode.SDL_SCANCODE_DISPLAYSWITCH | SDLK_SCANCODE_MASK,
-			SDLK_KBDILLUMTOGGLE =
-			(int)SDL_Scancode.SDL_SCANCODE_KBDILLUMTOGGLE | SDLK_SCANCODE_MASK,
-			SDLK_KBDILLUMDOWN = (int)SDL_Scancode.SDL_SCANCODE_KBDILLUMDOWN | SDLK_SCANCODE_MASK,
-			SDLK_KBDILLUMUP = (int)SDL_Scancode.SDL_SCANCODE_KBDILLUMUP | SDLK_SCANCODE_MASK,
-			SDLK_EJECT = (int)SDL_Scancode.SDL_SCANCODE_EJECT | SDLK_SCANCODE_MASK,
-			SDLK_SLEEP = (int)SDL_Scancode.SDL_SCANCODE_SLEEP | SDLK_SCANCODE_MASK
-		}
-	}
+    public static class SDL
+    {
+
+
+        public const int SDL_BUTTON_LEFT =    1;
+        public const int SDL_BUTTON_MIDDLE =    2;
+        public const int SDL_BUTTON_RIGHT =    3;
+        public const int SDL_BUTTON_X1 =    4;
+        public const int SDL_BUTTON_X2 =    5;
+        public const int SDL_BUTTON_LMASK =    (1 << ((int)SDL_BUTTON_LEFT - 1));
+        public const int SDL_BUTTON_MMASK =    (1 << ((int)SDL_BUTTON_MIDDLE - 1));
+        public const int SDL_BUTTON_RMASK =    (1 << ((int)SDL_BUTTON_RIGHT - 1));
+        public const int SDL_BUTTON_X1MASK = (1 << ((int)SDL_BUTTON_X1 - 1));
+        public const int SDL_BUTTON_X2MASK = (1 << ((int)SDL_BUTTON_X2 - 1));
+
+        public const byte SDL_HAT_CENTERED =    0x00;
+        public const byte SDL_HAT_UP =        0x01;
+        public const byte SDL_HAT_RIGHT =    0x02;
+        public const byte SDL_HAT_DOWN =    0x04;
+        public const byte SDL_HAT_LEFT =    0x08;
+        public const byte SDL_HAT_RIGHTUP =    SDL_HAT_RIGHT | SDL_HAT_UP;
+        public const byte SDL_HAT_RIGHTDOWN =    SDL_HAT_RIGHT | SDL_HAT_DOWN;
+        public const byte SDL_HAT_LEFTUP =    SDL_HAT_LEFT | SDL_HAT_UP;
+        public const byte SDL_HAT_LEFTDOWN =    SDL_HAT_LEFT | SDL_HAT_DOWN;
+
+        public enum SDL_GameControllerButton
+        {
+            SDL_CONTROLLER_BUTTON_INVALID = -1,
+            SDL_CONTROLLER_BUTTON_A,
+            SDL_CONTROLLER_BUTTON_B,
+            SDL_CONTROLLER_BUTTON_X,
+            SDL_CONTROLLER_BUTTON_Y,
+            SDL_CONTROLLER_BUTTON_BACK,
+            SDL_CONTROLLER_BUTTON_GUIDE,
+            SDL_CONTROLLER_BUTTON_START,
+            SDL_CONTROLLER_BUTTON_LEFTSTICK,
+            SDL_CONTROLLER_BUTTON_RIGHTSTICK,
+            SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
+            SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
+            SDL_CONTROLLER_BUTTON_DPAD_UP,
+            SDL_CONTROLLER_BUTTON_DPAD_DOWN,
+            SDL_CONTROLLER_BUTTON_DPAD_LEFT,
+            SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
+            SDL_CONTROLLER_BUTTON_MAX,
+        }
+
+        public enum SDL_GameControllerAxis
+        {
+            SDL_CONTROLLER_AXIS_INVALID = -1,
+            SDL_CONTROLLER_AXIS_LEFTX,
+            SDL_CONTROLLER_AXIS_LEFTY,
+            SDL_CONTROLLER_AXIS_RIGHTX,
+            SDL_CONTROLLER_AXIS_RIGHTY,
+            SDL_CONTROLLER_AXIS_TRIGGERLEFT,
+            SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
+            SDL_CONTROLLER_AXIS_MAX
+        }
+
+
+        /* Scancodes based off USB keyboard page (0x07) */
+        public enum SDL_Scancode
+        {
+            SDL_SCANCODE_UNKNOWN = 0,
+
+            SDL_SCANCODE_A = 4,
+            SDL_SCANCODE_B = 5,
+            SDL_SCANCODE_C = 6,
+            SDL_SCANCODE_D = 7,
+            SDL_SCANCODE_E = 8,
+            SDL_SCANCODE_F = 9,
+            SDL_SCANCODE_G = 10,
+            SDL_SCANCODE_H = 11,
+            SDL_SCANCODE_I = 12,
+            SDL_SCANCODE_J = 13,
+            SDL_SCANCODE_K = 14,
+            SDL_SCANCODE_L = 15,
+            SDL_SCANCODE_M = 16,
+            SDL_SCANCODE_N = 17,
+            SDL_SCANCODE_O = 18,
+            SDL_SCANCODE_P = 19,
+            SDL_SCANCODE_Q = 20,
+            SDL_SCANCODE_R = 21,
+            SDL_SCANCODE_S = 22,
+            SDL_SCANCODE_T = 23,
+            SDL_SCANCODE_U = 24,
+            SDL_SCANCODE_V = 25,
+            SDL_SCANCODE_W = 26,
+            SDL_SCANCODE_X = 27,
+            SDL_SCANCODE_Y = 28,
+            SDL_SCANCODE_Z = 29,
+
+            SDL_SCANCODE_1 = 30,
+            SDL_SCANCODE_2 = 31,
+            SDL_SCANCODE_3 = 32,
+            SDL_SCANCODE_4 = 33,
+            SDL_SCANCODE_5 = 34,
+            SDL_SCANCODE_6 = 35,
+            SDL_SCANCODE_7 = 36,
+            SDL_SCANCODE_8 = 37,
+            SDL_SCANCODE_9 = 38,
+            SDL_SCANCODE_0 = 39,
+
+            SDL_SCANCODE_RETURN = 40,
+            SDL_SCANCODE_ESCAPE = 41,
+            SDL_SCANCODE_BACKSPACE = 42,
+            SDL_SCANCODE_TAB = 43,
+            SDL_SCANCODE_SPACE = 44,
+
+            SDL_SCANCODE_MINUS = 45,
+            SDL_SCANCODE_EQUALS = 46,
+            SDL_SCANCODE_LEFTBRACKET = 47,
+            SDL_SCANCODE_RIGHTBRACKET = 48,
+            SDL_SCANCODE_BACKSLASH = 49,
+            SDL_SCANCODE_NONUSHASH = 50,
+            SDL_SCANCODE_SEMICOLON = 51,
+            SDL_SCANCODE_APOSTROPHE = 52,
+            SDL_SCANCODE_GRAVE = 53,
+            SDL_SCANCODE_COMMA = 54,
+            SDL_SCANCODE_PERIOD = 55,
+            SDL_SCANCODE_SLASH = 56,
+
+            SDL_SCANCODE_CAPSLOCK = 57,
+
+            SDL_SCANCODE_F1 = 58,
+            SDL_SCANCODE_F2 = 59,
+            SDL_SCANCODE_F3 = 60,
+            SDL_SCANCODE_F4 = 61,
+            SDL_SCANCODE_F5 = 62,
+            SDL_SCANCODE_F6 = 63,
+            SDL_SCANCODE_F7 = 64,
+            SDL_SCANCODE_F8 = 65,
+            SDL_SCANCODE_F9 = 66,
+            SDL_SCANCODE_F10 = 67,
+            SDL_SCANCODE_F11 = 68,
+            SDL_SCANCODE_F12 = 69,
+
+            SDL_SCANCODE_PRINTSCREEN = 70,
+            SDL_SCANCODE_SCROLLLOCK = 71,
+            SDL_SCANCODE_PAUSE = 72,
+            SDL_SCANCODE_INSERT = 73,
+            SDL_SCANCODE_HOME = 74,
+            SDL_SCANCODE_PAGEUP = 75,
+            SDL_SCANCODE_DELETE = 76,
+            SDL_SCANCODE_END = 77,
+            SDL_SCANCODE_PAGEDOWN = 78,
+            SDL_SCANCODE_RIGHT = 79,
+            SDL_SCANCODE_LEFT = 80,
+            SDL_SCANCODE_DOWN = 81,
+            SDL_SCANCODE_UP = 82,
+
+            SDL_SCANCODE_NUMLOCKCLEAR = 83,
+            SDL_SCANCODE_KP_DIVIDE = 84,
+            SDL_SCANCODE_KP_MULTIPLY = 85,
+            SDL_SCANCODE_KP_MINUS = 86,
+            SDL_SCANCODE_KP_PLUS = 87,
+            SDL_SCANCODE_KP_ENTER = 88,
+            SDL_SCANCODE_KP_1 = 89,
+            SDL_SCANCODE_KP_2 = 90,
+            SDL_SCANCODE_KP_3 = 91,
+            SDL_SCANCODE_KP_4 = 92,
+            SDL_SCANCODE_KP_5 = 93,
+            SDL_SCANCODE_KP_6 = 94,
+            SDL_SCANCODE_KP_7 = 95,
+            SDL_SCANCODE_KP_8 = 96,
+            SDL_SCANCODE_KP_9 = 97,
+            SDL_SCANCODE_KP_0 = 98,
+            SDL_SCANCODE_KP_PERIOD = 99,
+
+            SDL_SCANCODE_NONUSBACKSLASH = 100,
+            SDL_SCANCODE_APPLICATION = 101,
+            SDL_SCANCODE_POWER = 102,
+            SDL_SCANCODE_KP_EQUALS = 103,
+            SDL_SCANCODE_F13 = 104,
+            SDL_SCANCODE_F14 = 105,
+            SDL_SCANCODE_F15 = 106,
+            SDL_SCANCODE_F16 = 107,
+            SDL_SCANCODE_F17 = 108,
+            SDL_SCANCODE_F18 = 109,
+            SDL_SCANCODE_F19 = 110,
+            SDL_SCANCODE_F20 = 111,
+            SDL_SCANCODE_F21 = 112,
+            SDL_SCANCODE_F22 = 113,
+            SDL_SCANCODE_F23 = 114,
+            SDL_SCANCODE_F24 = 115,
+            SDL_SCANCODE_EXECUTE = 116,
+            SDL_SCANCODE_HELP = 117,
+            SDL_SCANCODE_MENU = 118,
+            SDL_SCANCODE_SELECT = 119,
+            SDL_SCANCODE_STOP = 120,
+            SDL_SCANCODE_AGAIN = 121,
+            SDL_SCANCODE_UNDO = 122,
+            SDL_SCANCODE_CUT = 123,
+            SDL_SCANCODE_COPY = 124,
+            SDL_SCANCODE_PASTE = 125,
+            SDL_SCANCODE_FIND = 126,
+            SDL_SCANCODE_MUTE = 127,
+            SDL_SCANCODE_VOLUMEUP = 128,
+            SDL_SCANCODE_VOLUMEDOWN = 129,
+            /* not sure whether there's a reason to enable these */
+            /*    SDL_SCANCODE_LOCKINGCAPSLOCK = 130,  */
+            /*    SDL_SCANCODE_LOCKINGNUMLOCK = 131, */
+            /*    SDL_SCANCODE_LOCKINGSCROLLLOCK = 132, */
+            SDL_SCANCODE_KP_COMMA = 133,
+            SDL_SCANCODE_KP_EQUALSAS400 = 134,
+
+            SDL_SCANCODE_INTERNATIONAL1 = 135,
+            SDL_SCANCODE_INTERNATIONAL2 = 136,
+            SDL_SCANCODE_INTERNATIONAL3 = 137,
+            SDL_SCANCODE_INTERNATIONAL4 = 138,
+            SDL_SCANCODE_INTERNATIONAL5 = 139,
+            SDL_SCANCODE_INTERNATIONAL6 = 140,
+            SDL_SCANCODE_INTERNATIONAL7 = 141,
+            SDL_SCANCODE_INTERNATIONAL8 = 142,
+            SDL_SCANCODE_INTERNATIONAL9 = 143,
+            SDL_SCANCODE_LANG1 = 144,
+            SDL_SCANCODE_LANG2 = 145,
+            SDL_SCANCODE_LANG3 = 146,
+            SDL_SCANCODE_LANG4 = 147,
+            SDL_SCANCODE_LANG5 = 148,
+            SDL_SCANCODE_LANG6 = 149,
+            SDL_SCANCODE_LANG7 = 150,
+            SDL_SCANCODE_LANG8 = 151,
+            SDL_SCANCODE_LANG9 = 152,
+
+            SDL_SCANCODE_ALTERASE = 153,
+            SDL_SCANCODE_SYSREQ = 154,
+            SDL_SCANCODE_CANCEL = 155,
+            SDL_SCANCODE_CLEAR = 156,
+            SDL_SCANCODE_PRIOR = 157,
+            SDL_SCANCODE_RETURN2 = 158,
+            SDL_SCANCODE_SEPARATOR = 159,
+            SDL_SCANCODE_OUT = 160,
+            SDL_SCANCODE_OPER = 161,
+            SDL_SCANCODE_CLEARAGAIN = 162,
+            SDL_SCANCODE_CRSEL = 163,
+            SDL_SCANCODE_EXSEL = 164,
+
+            SDL_SCANCODE_KP_00 = 176,
+            SDL_SCANCODE_KP_000 = 177,
+            SDL_SCANCODE_THOUSANDSSEPARATOR = 178,
+            SDL_SCANCODE_DECIMALSEPARATOR = 179,
+            SDL_SCANCODE_CURRENCYUNIT = 180,
+            SDL_SCANCODE_CURRENCYSUBUNIT = 181,
+            SDL_SCANCODE_KP_LEFTPAREN = 182,
+            SDL_SCANCODE_KP_RIGHTPAREN = 183,
+            SDL_SCANCODE_KP_LEFTBRACE = 184,
+            SDL_SCANCODE_KP_RIGHTBRACE = 185,
+            SDL_SCANCODE_KP_TAB = 186,
+            SDL_SCANCODE_KP_BACKSPACE = 187,
+            SDL_SCANCODE_KP_A = 188,
+            SDL_SCANCODE_KP_B = 189,
+            SDL_SCANCODE_KP_C = 190,
+            SDL_SCANCODE_KP_D = 191,
+            SDL_SCANCODE_KP_E = 192,
+            SDL_SCANCODE_KP_F = 193,
+            SDL_SCANCODE_KP_XOR = 194,
+            SDL_SCANCODE_KP_POWER = 195,
+            SDL_SCANCODE_KP_PERCENT = 196,
+            SDL_SCANCODE_KP_LESS = 197,
+            SDL_SCANCODE_KP_GREATER = 198,
+            SDL_SCANCODE_KP_AMPERSAND = 199,
+            SDL_SCANCODE_KP_DBLAMPERSAND = 200,
+            SDL_SCANCODE_KP_VERTICALBAR = 201,
+            SDL_SCANCODE_KP_DBLVERTICALBAR = 202,
+            SDL_SCANCODE_KP_COLON = 203,
+            SDL_SCANCODE_KP_HASH = 204,
+            SDL_SCANCODE_KP_SPACE = 205,
+            SDL_SCANCODE_KP_AT = 206,
+            SDL_SCANCODE_KP_EXCLAM = 207,
+            SDL_SCANCODE_KP_MEMSTORE = 208,
+            SDL_SCANCODE_KP_MEMRECALL = 209,
+            SDL_SCANCODE_KP_MEMCLEAR = 210,
+            SDL_SCANCODE_KP_MEMADD = 211,
+            SDL_SCANCODE_KP_MEMSUBTRACT = 212,
+            SDL_SCANCODE_KP_MEMMULTIPLY = 213,
+            SDL_SCANCODE_KP_MEMDIVIDE = 214,
+            SDL_SCANCODE_KP_PLUSMINUS = 215,
+            SDL_SCANCODE_KP_CLEAR = 216,
+            SDL_SCANCODE_KP_CLEARENTRY = 217,
+            SDL_SCANCODE_KP_BINARY = 218,
+            SDL_SCANCODE_KP_OCTAL = 219,
+            SDL_SCANCODE_KP_DECIMAL = 220,
+            SDL_SCANCODE_KP_HEXADECIMAL = 221,
+
+            SDL_SCANCODE_LCTRL = 224,
+            SDL_SCANCODE_LSHIFT = 225,
+            SDL_SCANCODE_LALT = 226,
+            SDL_SCANCODE_LGUI = 227,
+            SDL_SCANCODE_RCTRL = 228,
+            SDL_SCANCODE_RSHIFT = 229,
+            SDL_SCANCODE_RALT = 230,
+            SDL_SCANCODE_RGUI = 231,
+
+            SDL_SCANCODE_MODE = 257,
+
+            /* These come from the USB consumer page (0x0C) */
+            SDL_SCANCODE_AUDIONEXT = 258,
+            SDL_SCANCODE_AUDIOPREV = 259,
+            SDL_SCANCODE_AUDIOSTOP = 260,
+            SDL_SCANCODE_AUDIOPLAY = 261,
+            SDL_SCANCODE_AUDIOMUTE = 262,
+            SDL_SCANCODE_MEDIASELECT = 263,
+            SDL_SCANCODE_WWW = 264,
+            SDL_SCANCODE_MAIL = 265,
+            SDL_SCANCODE_CALCULATOR = 266,
+            SDL_SCANCODE_COMPUTER = 267,
+            SDL_SCANCODE_AC_SEARCH = 268,
+            SDL_SCANCODE_AC_HOME = 269,
+            SDL_SCANCODE_AC_BACK = 270,
+            SDL_SCANCODE_AC_FORWARD = 271,
+            SDL_SCANCODE_AC_STOP = 272,
+            SDL_SCANCODE_AC_REFRESH = 273,
+            SDL_SCANCODE_AC_BOOKMARKS = 274,
+
+            /* These come from other sources, and are mostly mac related */
+            SDL_SCANCODE_BRIGHTNESSDOWN = 275,
+            SDL_SCANCODE_BRIGHTNESSUP = 276,
+            SDL_SCANCODE_DISPLAYSWITCH = 277,
+            SDL_SCANCODE_KBDILLUMTOGGLE = 278,
+            SDL_SCANCODE_KBDILLUMDOWN = 279,
+            SDL_SCANCODE_KBDILLUMUP = 280,
+            SDL_SCANCODE_EJECT = 281,
+            SDL_SCANCODE_SLEEP = 282,
+
+            SDL_SCANCODE_APP1 = 283,
+            SDL_SCANCODE_APP2 = 284,
+
+            /* This is not a key, simply marks the number of scancodes
+             * so that you know how big to make your arrays. */
+            SDL_NUM_SCANCODES = 512
+        }
+
+        public const int SDLK_SCANCODE_MASK = (1 << 30);
+
+        public enum SDL_Keycode
+        {
+            SDLK_UNKNOWN = 0,
+
+            SDLK_RETURN = '\r',
+            SDLK_ESCAPE = 27,
+            // '\033'
+            SDLK_BACKSPACE = '\b',
+            SDLK_TAB = '\t',
+            SDLK_SPACE = ' ',
+            SDLK_EXCLAIM = '!',
+            SDLK_QUOTEDBL = '"',
+            SDLK_HASH = '#',
+            SDLK_PERCENT = '%',
+            SDLK_DOLLAR = '$',
+            SDLK_AMPERSAND = '&',
+            SDLK_QUOTE = '\'',
+            SDLK_LEFTPAREN = '(',
+            SDLK_RIGHTPAREN = ')',
+            SDLK_ASTERISK = '*',
+            SDLK_PLUS = '+',
+            SDLK_COMMA = ',',
+            SDLK_MINUS = '-',
+            SDLK_PERIOD = '.',
+            SDLK_SLASH = '/',
+            SDLK_0 = '0',
+            SDLK_1 = '1',
+            SDLK_2 = '2',
+            SDLK_3 = '3',
+            SDLK_4 = '4',
+            SDLK_5 = '5',
+            SDLK_6 = '6',
+            SDLK_7 = '7',
+            SDLK_8 = '8',
+            SDLK_9 = '9',
+            SDLK_COLON = ':',
+            SDLK_SEMICOLON = ';',
+            SDLK_LESS = '<',
+            SDLK_EQUALS = '=',
+            SDLK_GREATER = '>',
+            SDLK_QUESTION = '?',
+            SDLK_AT = '@',
+            /*
+            Skip uppercase letters
+            */
+            SDLK_LEFTBRACKET = '[',
+            SDLK_BACKSLASH = '\\',
+            SDLK_RIGHTBRACKET = ']',
+            SDLK_CARET = '^',
+            SDLK_UNDERSCORE = '_',
+            SDLK_BACKQUOTE = '`',
+            SDLK_a = 'a',
+            SDLK_b = 'b',
+            SDLK_c = 'c',
+            SDLK_d = 'd',
+            SDLK_e = 'e',
+            SDLK_f = 'f',
+            SDLK_g = 'g',
+            SDLK_h = 'h',
+            SDLK_i = 'i',
+            SDLK_j = 'j',
+            SDLK_k = 'k',
+            SDLK_l = 'l',
+            SDLK_m = 'm',
+            SDLK_n = 'n',
+            SDLK_o = 'o',
+            SDLK_p = 'p',
+            SDLK_q = 'q',
+            SDLK_r = 'r',
+            SDLK_s = 's',
+            SDLK_t = 't',
+            SDLK_u = 'u',
+            SDLK_v = 'v',
+            SDLK_w = 'w',
+            SDLK_x = 'x',
+            SDLK_y = 'y',
+            SDLK_z = 'z',
+
+            SDLK_CAPSLOCK = (int)SDL_Scancode.SDL_SCANCODE_CAPSLOCK | SDLK_SCANCODE_MASK,
+
+            SDLK_F1 = (int)SDL_Scancode.SDL_SCANCODE_F1 | SDLK_SCANCODE_MASK,
+            SDLK_F2 = (int)SDL_Scancode.SDL_SCANCODE_F2 | SDLK_SCANCODE_MASK,
+            SDLK_F3 = (int)SDL_Scancode.SDL_SCANCODE_F3 | SDLK_SCANCODE_MASK,
+            SDLK_F4 = (int)SDL_Scancode.SDL_SCANCODE_F4 | SDLK_SCANCODE_MASK,
+            SDLK_F5 = (int)SDL_Scancode.SDL_SCANCODE_F5 | SDLK_SCANCODE_MASK,
+            SDLK_F6 = (int)SDL_Scancode.SDL_SCANCODE_F6 | SDLK_SCANCODE_MASK,
+            SDLK_F7 = (int)SDL_Scancode.SDL_SCANCODE_F7 | SDLK_SCANCODE_MASK,
+            SDLK_F8 = (int)SDL_Scancode.SDL_SCANCODE_F8 | SDLK_SCANCODE_MASK,
+            SDLK_F9 = (int)SDL_Scancode.SDL_SCANCODE_F9 | SDLK_SCANCODE_MASK,
+            SDLK_F10 = (int)SDL_Scancode.SDL_SCANCODE_F10 | SDLK_SCANCODE_MASK,
+            SDLK_F11 = (int)SDL_Scancode.SDL_SCANCODE_F11 | SDLK_SCANCODE_MASK,
+            SDLK_F12 = (int)SDL_Scancode.SDL_SCANCODE_F12 | SDLK_SCANCODE_MASK,
+
+            SDLK_PRINTSCREEN = (int)SDL_Scancode.SDL_SCANCODE_PRINTSCREEN | SDLK_SCANCODE_MASK,
+            SDLK_SCROLLLOCK = (int)SDL_Scancode.SDL_SCANCODE_SCROLLLOCK | SDLK_SCANCODE_MASK,
+            SDLK_PAUSE = (int)SDL_Scancode.SDL_SCANCODE_PAUSE | SDLK_SCANCODE_MASK,
+            SDLK_INSERT = (int)SDL_Scancode.SDL_SCANCODE_INSERT | SDLK_SCANCODE_MASK,
+            SDLK_HOME = (int)SDL_Scancode.SDL_SCANCODE_HOME | SDLK_SCANCODE_MASK,
+            SDLK_PAGEUP = (int)SDL_Scancode.SDL_SCANCODE_PAGEUP | SDLK_SCANCODE_MASK,
+            SDLK_DELETE = 127,
+            SDLK_END = (int)SDL_Scancode.SDL_SCANCODE_END | SDLK_SCANCODE_MASK,
+            SDLK_PAGEDOWN = (int)SDL_Scancode.SDL_SCANCODE_PAGEDOWN | SDLK_SCANCODE_MASK,
+            SDLK_RIGHT = (int)SDL_Scancode.SDL_SCANCODE_RIGHT | SDLK_SCANCODE_MASK,
+            SDLK_LEFT = (int)SDL_Scancode.SDL_SCANCODE_LEFT | SDLK_SCANCODE_MASK,
+            SDLK_DOWN = (int)SDL_Scancode.SDL_SCANCODE_DOWN | SDLK_SCANCODE_MASK,
+            SDLK_UP = (int)SDL_Scancode.SDL_SCANCODE_UP | SDLK_SCANCODE_MASK,
+
+            SDLK_NUMLOCKCLEAR = (int)SDL_Scancode.SDL_SCANCODE_NUMLOCKCLEAR | SDLK_SCANCODE_MASK,
+            SDLK_KP_DIVIDE = (int)SDL_Scancode.SDL_SCANCODE_KP_DIVIDE | SDLK_SCANCODE_MASK,
+            SDLK_KP_MULTIPLY = (int)SDL_Scancode.SDL_SCANCODE_KP_MULTIPLY | SDLK_SCANCODE_MASK,
+            SDLK_KP_MINUS = (int)SDL_Scancode.SDL_SCANCODE_KP_MINUS | SDLK_SCANCODE_MASK,
+            SDLK_KP_PLUS = (int)SDL_Scancode.SDL_SCANCODE_KP_PLUS | SDLK_SCANCODE_MASK,
+            SDLK_KP_ENTER = (int)SDL_Scancode.SDL_SCANCODE_KP_ENTER | SDLK_SCANCODE_MASK,
+            SDLK_KP_1 = (int)SDL_Scancode.SDL_SCANCODE_KP_1 | SDLK_SCANCODE_MASK,
+            SDLK_KP_2 = (int)SDL_Scancode.SDL_SCANCODE_KP_2 | SDLK_SCANCODE_MASK,
+            SDLK_KP_3 = (int)SDL_Scancode.SDL_SCANCODE_KP_3 | SDLK_SCANCODE_MASK,
+            SDLK_KP_4 = (int)SDL_Scancode.SDL_SCANCODE_KP_4 | SDLK_SCANCODE_MASK,
+            SDLK_KP_5 = (int)SDL_Scancode.SDL_SCANCODE_KP_5 | SDLK_SCANCODE_MASK,
+            SDLK_KP_6 = (int)SDL_Scancode.SDL_SCANCODE_KP_6 | SDLK_SCANCODE_MASK,
+            SDLK_KP_7 = (int)SDL_Scancode.SDL_SCANCODE_KP_7 | SDLK_SCANCODE_MASK,
+            SDLK_KP_8 = (int)SDL_Scancode.SDL_SCANCODE_KP_8 | SDLK_SCANCODE_MASK,
+            SDLK_KP_9 = (int)SDL_Scancode.SDL_SCANCODE_KP_9 | SDLK_SCANCODE_MASK,
+            SDLK_KP_0 = (int)SDL_Scancode.SDL_SCANCODE_KP_0 | SDLK_SCANCODE_MASK,
+            SDLK_KP_PERIOD = (int)SDL_Scancode.SDL_SCANCODE_KP_PERIOD | SDLK_SCANCODE_MASK,
+
+            SDLK_APPLICATION = (int)SDL_Scancode.SDL_SCANCODE_APPLICATION | SDLK_SCANCODE_MASK,
+            SDLK_POWER = (int)SDL_Scancode.SDL_SCANCODE_POWER | SDLK_SCANCODE_MASK,
+            SDLK_KP_EQUALS = (int)SDL_Scancode.SDL_SCANCODE_KP_EQUALS | SDLK_SCANCODE_MASK,
+            SDLK_F13 = (int)SDL_Scancode.SDL_SCANCODE_F13 | SDLK_SCANCODE_MASK,
+            SDLK_F14 = (int)SDL_Scancode.SDL_SCANCODE_F14 | SDLK_SCANCODE_MASK,
+            SDLK_F15 = (int)SDL_Scancode.SDL_SCANCODE_F15 | SDLK_SCANCODE_MASK,
+            SDLK_F16 = (int)SDL_Scancode.SDL_SCANCODE_F16 | SDLK_SCANCODE_MASK,
+            SDLK_F17 = (int)SDL_Scancode.SDL_SCANCODE_F17 | SDLK_SCANCODE_MASK,
+            SDLK_F18 = (int)SDL_Scancode.SDL_SCANCODE_F18 | SDLK_SCANCODE_MASK,
+            SDLK_F19 = (int)SDL_Scancode.SDL_SCANCODE_F19 | SDLK_SCANCODE_MASK,
+            SDLK_F20 = (int)SDL_Scancode.SDL_SCANCODE_F20 | SDLK_SCANCODE_MASK,
+            SDLK_F21 = (int)SDL_Scancode.SDL_SCANCODE_F21 | SDLK_SCANCODE_MASK,
+            SDLK_F22 = (int)SDL_Scancode.SDL_SCANCODE_F22 | SDLK_SCANCODE_MASK,
+            SDLK_F23 = (int)SDL_Scancode.SDL_SCANCODE_F23 | SDLK_SCANCODE_MASK,
+            SDLK_F24 = (int)SDL_Scancode.SDL_SCANCODE_F24 | SDLK_SCANCODE_MASK,
+            SDLK_EXECUTE = (int)SDL_Scancode.SDL_SCANCODE_EXECUTE | SDLK_SCANCODE_MASK,
+            SDLK_HELP = (int)SDL_Scancode.SDL_SCANCODE_HELP | SDLK_SCANCODE_MASK,
+            SDLK_MENU = (int)SDL_Scancode.SDL_SCANCODE_MENU | SDLK_SCANCODE_MASK,
+            SDLK_SELECT = (int)SDL_Scancode.SDL_SCANCODE_SELECT | SDLK_SCANCODE_MASK,
+            SDLK_STOP = (int)SDL_Scancode.SDL_SCANCODE_STOP | SDLK_SCANCODE_MASK,
+            SDLK_AGAIN = (int)SDL_Scancode.SDL_SCANCODE_AGAIN | SDLK_SCANCODE_MASK,
+            SDLK_UNDO = (int)SDL_Scancode.SDL_SCANCODE_UNDO | SDLK_SCANCODE_MASK,
+            SDLK_CUT = (int)SDL_Scancode.SDL_SCANCODE_CUT | SDLK_SCANCODE_MASK,
+            SDLK_COPY = (int)SDL_Scancode.SDL_SCANCODE_COPY | SDLK_SCANCODE_MASK,
+            SDLK_PASTE = (int)SDL_Scancode.SDL_SCANCODE_PASTE | SDLK_SCANCODE_MASK,
+            SDLK_FIND = (int)SDL_Scancode.SDL_SCANCODE_FIND | SDLK_SCANCODE_MASK,
+            SDLK_MUTE = (int)SDL_Scancode.SDL_SCANCODE_MUTE | SDLK_SCANCODE_MASK,
+            SDLK_VOLUMEUP = (int)SDL_Scancode.SDL_SCANCODE_VOLUMEUP | SDLK_SCANCODE_MASK,
+            SDLK_VOLUMEDOWN = (int)SDL_Scancode.SDL_SCANCODE_VOLUMEDOWN | SDLK_SCANCODE_MASK,
+            SDLK_KP_COMMA = (int)SDL_Scancode.SDL_SCANCODE_KP_COMMA | SDLK_SCANCODE_MASK,
+            SDLK_KP_EQUALSAS400 =
+            (int)SDL_Scancode.SDL_SCANCODE_KP_EQUALSAS400 | SDLK_SCANCODE_MASK,
+
+            SDLK_ALTERASE = (int)SDL_Scancode.SDL_SCANCODE_ALTERASE | SDLK_SCANCODE_MASK,
+            SDLK_SYSREQ = (int)SDL_Scancode.SDL_SCANCODE_SYSREQ | SDLK_SCANCODE_MASK,
+            SDLK_CANCEL = (int)SDL_Scancode.SDL_SCANCODE_CANCEL | SDLK_SCANCODE_MASK,
+            SDLK_CLEAR = (int)SDL_Scancode.SDL_SCANCODE_CLEAR | SDLK_SCANCODE_MASK,
+            SDLK_PRIOR = (int)SDL_Scancode.SDL_SCANCODE_PRIOR | SDLK_SCANCODE_MASK,
+            SDLK_RETURN2 = (int)SDL_Scancode.SDL_SCANCODE_RETURN2 | SDLK_SCANCODE_MASK,
+            SDLK_SEPARATOR = (int)SDL_Scancode.SDL_SCANCODE_SEPARATOR | SDLK_SCANCODE_MASK,
+            SDLK_OUT = (int)SDL_Scancode.SDL_SCANCODE_OUT | SDLK_SCANCODE_MASK,
+            SDLK_OPER = (int)SDL_Scancode.SDL_SCANCODE_OPER | SDLK_SCANCODE_MASK,
+            SDLK_CLEARAGAIN = (int)SDL_Scancode.SDL_SCANCODE_CLEARAGAIN | SDLK_SCANCODE_MASK,
+            SDLK_CRSEL = (int)SDL_Scancode.SDL_SCANCODE_CRSEL | SDLK_SCANCODE_MASK,
+            SDLK_EXSEL = (int)SDL_Scancode.SDL_SCANCODE_EXSEL | SDLK_SCANCODE_MASK,
+
+            SDLK_KP_00 = (int)SDL_Scancode.SDL_SCANCODE_KP_00 | SDLK_SCANCODE_MASK,
+            SDLK_KP_000 = (int)SDL_Scancode.SDL_SCANCODE_KP_000 | SDLK_SCANCODE_MASK,
+            SDLK_THOUSANDSSEPARATOR =
+            (int)SDL_Scancode.SDL_SCANCODE_THOUSANDSSEPARATOR | SDLK_SCANCODE_MASK,
+            SDLK_DECIMALSEPARATOR =
+            (int)SDL_Scancode.SDL_SCANCODE_DECIMALSEPARATOR | SDLK_SCANCODE_MASK,
+            SDLK_CURRENCYUNIT = (int)SDL_Scancode.SDL_SCANCODE_CURRENCYUNIT | SDLK_SCANCODE_MASK,
+            SDLK_CURRENCYSUBUNIT =
+            (int)SDL_Scancode.SDL_SCANCODE_CURRENCYSUBUNIT | SDLK_SCANCODE_MASK,
+            SDLK_KP_LEFTPAREN = (int)SDL_Scancode.SDL_SCANCODE_KP_LEFTPAREN | SDLK_SCANCODE_MASK,
+            SDLK_KP_RIGHTPAREN = (int)SDL_Scancode.SDL_SCANCODE_KP_RIGHTPAREN | SDLK_SCANCODE_MASK,
+            SDLK_KP_LEFTBRACE = (int)SDL_Scancode.SDL_SCANCODE_KP_LEFTBRACE | SDLK_SCANCODE_MASK,
+            SDLK_KP_RIGHTBRACE = (int)SDL_Scancode.SDL_SCANCODE_KP_RIGHTBRACE | SDLK_SCANCODE_MASK,
+            SDLK_KP_TAB = (int)SDL_Scancode.SDL_SCANCODE_KP_TAB | SDLK_SCANCODE_MASK,
+            SDLK_KP_BACKSPACE = (int)SDL_Scancode.SDL_SCANCODE_KP_BACKSPACE | SDLK_SCANCODE_MASK,
+            SDLK_KP_A = (int)SDL_Scancode.SDL_SCANCODE_KP_A | SDLK_SCANCODE_MASK,
+            SDLK_KP_B = (int)SDL_Scancode.SDL_SCANCODE_KP_B | SDLK_SCANCODE_MASK,
+            SDLK_KP_C = (int)SDL_Scancode.SDL_SCANCODE_KP_C | SDLK_SCANCODE_MASK,
+            SDLK_KP_D = (int)SDL_Scancode.SDL_SCANCODE_KP_D | SDLK_SCANCODE_MASK,
+            SDLK_KP_E = (int)SDL_Scancode.SDL_SCANCODE_KP_E | SDLK_SCANCODE_MASK,
+            SDLK_KP_F = (int)SDL_Scancode.SDL_SCANCODE_KP_F | SDLK_SCANCODE_MASK,
+            SDLK_KP_XOR = (int)SDL_Scancode.SDL_SCANCODE_KP_XOR | SDLK_SCANCODE_MASK,
+            SDLK_KP_POWER = (int)SDL_Scancode.SDL_SCANCODE_KP_POWER | SDLK_SCANCODE_MASK,
+            SDLK_KP_PERCENT = (int)SDL_Scancode.SDL_SCANCODE_KP_PERCENT | SDLK_SCANCODE_MASK,
+            SDLK_KP_LESS = (int)SDL_Scancode.SDL_SCANCODE_KP_LESS | SDLK_SCANCODE_MASK,
+            SDLK_KP_GREATER = (int)SDL_Scancode.SDL_SCANCODE_KP_GREATER | SDLK_SCANCODE_MASK,
+            SDLK_KP_AMPERSAND = (int)SDL_Scancode.SDL_SCANCODE_KP_AMPERSAND | SDLK_SCANCODE_MASK,
+            SDLK_KP_DBLAMPERSAND =
+            (int)SDL_Scancode.SDL_SCANCODE_KP_DBLAMPERSAND | SDLK_SCANCODE_MASK,
+            SDLK_KP_VERTICALBAR =
+            (int)SDL_Scancode.SDL_SCANCODE_KP_VERTICALBAR | SDLK_SCANCODE_MASK,
+            SDLK_KP_DBLVERTICALBAR =
+            (int)SDL_Scancode.SDL_SCANCODE_KP_DBLVERTICALBAR | SDLK_SCANCODE_MASK,
+            SDLK_KP_COLON = (int)SDL_Scancode.SDL_SCANCODE_KP_COLON | SDLK_SCANCODE_MASK,
+            SDLK_KP_HASH = (int)SDL_Scancode.SDL_SCANCODE_KP_HASH | SDLK_SCANCODE_MASK,
+            SDLK_KP_SPACE = (int)SDL_Scancode.SDL_SCANCODE_KP_SPACE | SDLK_SCANCODE_MASK,
+            SDLK_KP_AT = (int)SDL_Scancode.SDL_SCANCODE_KP_AT | SDLK_SCANCODE_MASK,
+            SDLK_KP_EXCLAM = (int)SDL_Scancode.SDL_SCANCODE_KP_EXCLAM | SDLK_SCANCODE_MASK,
+            SDLK_KP_MEMSTORE = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMSTORE | SDLK_SCANCODE_MASK,
+            SDLK_KP_MEMRECALL = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMRECALL | SDLK_SCANCODE_MASK,
+            SDLK_KP_MEMCLEAR = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMCLEAR | SDLK_SCANCODE_MASK,
+            SDLK_KP_MEMADD = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMADD | SDLK_SCANCODE_MASK,
+            SDLK_KP_MEMSUBTRACT =
+            (int)SDL_Scancode.SDL_SCANCODE_KP_MEMSUBTRACT | SDLK_SCANCODE_MASK,
+            SDLK_KP_MEMMULTIPLY =
+            (int)SDL_Scancode.SDL_SCANCODE_KP_MEMMULTIPLY | SDLK_SCANCODE_MASK,
+            SDLK_KP_MEMDIVIDE = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMDIVIDE | SDLK_SCANCODE_MASK,
+            SDLK_KP_PLUSMINUS = (int)SDL_Scancode.SDL_SCANCODE_KP_PLUSMINUS | SDLK_SCANCODE_MASK,
+            SDLK_KP_CLEAR = (int)SDL_Scancode.SDL_SCANCODE_KP_CLEAR | SDLK_SCANCODE_MASK,
+            SDLK_KP_CLEARENTRY = (int)SDL_Scancode.SDL_SCANCODE_KP_CLEARENTRY | SDLK_SCANCODE_MASK,
+            SDLK_KP_BINARY = (int)SDL_Scancode.SDL_SCANCODE_KP_BINARY | SDLK_SCANCODE_MASK,
+            SDLK_KP_OCTAL = (int)SDL_Scancode.SDL_SCANCODE_KP_OCTAL | SDLK_SCANCODE_MASK,
+            SDLK_KP_DECIMAL = (int)SDL_Scancode.SDL_SCANCODE_KP_DECIMAL | SDLK_SCANCODE_MASK,
+            SDLK_KP_HEXADECIMAL =
+            (int)SDL_Scancode.SDL_SCANCODE_KP_HEXADECIMAL | SDLK_SCANCODE_MASK,
+
+            SDLK_LCTRL = (int)SDL_Scancode.SDL_SCANCODE_LCTRL | SDLK_SCANCODE_MASK,
+            SDLK_LSHIFT = (int)SDL_Scancode.SDL_SCANCODE_LSHIFT | SDLK_SCANCODE_MASK,
+            SDLK_LALT = (int)SDL_Scancode.SDL_SCANCODE_LALT | SDLK_SCANCODE_MASK,
+            SDLK_LGUI = (int)SDL_Scancode.SDL_SCANCODE_LGUI | SDLK_SCANCODE_MASK,
+            SDLK_RCTRL = (int)SDL_Scancode.SDL_SCANCODE_RCTRL | SDLK_SCANCODE_MASK,
+            SDLK_RSHIFT = (int)SDL_Scancode.SDL_SCANCODE_RSHIFT | SDLK_SCANCODE_MASK,
+            SDLK_RALT = (int)SDL_Scancode.SDL_SCANCODE_RALT | SDLK_SCANCODE_MASK,
+            SDLK_RGUI = (int)SDL_Scancode.SDL_SCANCODE_RGUI | SDLK_SCANCODE_MASK,
+
+            SDLK_MODE = (int)SDL_Scancode.SDL_SCANCODE_MODE | SDLK_SCANCODE_MASK,
+
+            SDLK_AUDIONEXT = (int)SDL_Scancode.SDL_SCANCODE_AUDIONEXT | SDLK_SCANCODE_MASK,
+            SDLK_AUDIOPREV = (int)SDL_Scancode.SDL_SCANCODE_AUDIOPREV | SDLK_SCANCODE_MASK,
+            SDLK_AUDIOSTOP = (int)SDL_Scancode.SDL_SCANCODE_AUDIOSTOP | SDLK_SCANCODE_MASK,
+            SDLK_AUDIOPLAY = (int)SDL_Scancode.SDL_SCANCODE_AUDIOPLAY | SDLK_SCANCODE_MASK,
+            SDLK_AUDIOMUTE = (int)SDL_Scancode.SDL_SCANCODE_AUDIOMUTE | SDLK_SCANCODE_MASK,
+            SDLK_MEDIASELECT = (int)SDL_Scancode.SDL_SCANCODE_MEDIASELECT | SDLK_SCANCODE_MASK,
+            SDLK_WWW = (int)SDL_Scancode.SDL_SCANCODE_WWW | SDLK_SCANCODE_MASK,
+            SDLK_MAIL = (int)SDL_Scancode.SDL_SCANCODE_MAIL | SDLK_SCANCODE_MASK,
+            SDLK_CALCULATOR = (int)SDL_Scancode.SDL_SCANCODE_CALCULATOR | SDLK_SCANCODE_MASK,
+            SDLK_COMPUTER = (int)SDL_Scancode.SDL_SCANCODE_COMPUTER | SDLK_SCANCODE_MASK,
+            SDLK_AC_SEARCH = (int)SDL_Scancode.SDL_SCANCODE_AC_SEARCH | SDLK_SCANCODE_MASK,
+            SDLK_AC_HOME = (int)SDL_Scancode.SDL_SCANCODE_AC_HOME | SDLK_SCANCODE_MASK,
+            SDLK_AC_BACK = (int)SDL_Scancode.SDL_SCANCODE_AC_BACK | SDLK_SCANCODE_MASK,
+            SDLK_AC_FORWARD = (int)SDL_Scancode.SDL_SCANCODE_AC_FORWARD | SDLK_SCANCODE_MASK,
+            SDLK_AC_STOP = (int)SDL_Scancode.SDL_SCANCODE_AC_STOP | SDLK_SCANCODE_MASK,
+            SDLK_AC_REFRESH = (int)SDL_Scancode.SDL_SCANCODE_AC_REFRESH | SDLK_SCANCODE_MASK,
+            SDLK_AC_BOOKMARKS = (int)SDL_Scancode.SDL_SCANCODE_AC_BOOKMARKS | SDLK_SCANCODE_MASK,
+
+            SDLK_BRIGHTNESSDOWN =
+            (int)SDL_Scancode.SDL_SCANCODE_BRIGHTNESSDOWN | SDLK_SCANCODE_MASK,
+            SDLK_BRIGHTNESSUP = (int)SDL_Scancode.SDL_SCANCODE_BRIGHTNESSUP | SDLK_SCANCODE_MASK,
+            SDLK_DISPLAYSWITCH = (int)SDL_Scancode.SDL_SCANCODE_DISPLAYSWITCH | SDLK_SCANCODE_MASK,
+            SDLK_KBDILLUMTOGGLE =
+            (int)SDL_Scancode.SDL_SCANCODE_KBDILLUMTOGGLE | SDLK_SCANCODE_MASK,
+            SDLK_KBDILLUMDOWN = (int)SDL_Scancode.SDL_SCANCODE_KBDILLUMDOWN | SDLK_SCANCODE_MASK,
+            SDLK_KBDILLUMUP = (int)SDL_Scancode.SDL_SCANCODE_KBDILLUMUP | SDLK_SCANCODE_MASK,
+            SDLK_EJECT = (int)SDL_Scancode.SDL_SCANCODE_EJECT | SDLK_SCANCODE_MASK,
+            SDLK_SLEEP = (int)SDL_Scancode.SDL_SCANCODE_SLEEP | SDLK_SCANCODE_MASK
+        }
+    }
 
 }

+ 144 - 0
Script/AtomicNET/AtomicNET/Core/SDLEvents.cs

@@ -0,0 +1,144 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+    public static class SDLEvents
+    {
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        static extern int SDL_SendWindowEvent(IntPtr window, byte windowevent, int data1, int data2);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        static extern int SDL_SendAppEvent(byte eventType);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        static extern void SDL_SetMainReady();
+
+        public static void SetMainReady() => SDL_SetMainReady();
+
+        public static void SendWindowEvent(SdlWindowEvent wndEvent, int data1 = 0, int data2 = 0)
+        {
+            var graphics = AtomicNET.GetSubsystem<Graphics>();
+            SDL_SendWindowEvent(graphics.SDLWindow, (byte) wndEvent, data1, data2);
+        }
+
+        public static void SendAppEvent(SdlEventType eventType) => SDL_SendAppEvent((byte)eventType);
+    }
+
+    //see SDL_Video.h
+    public enum SdlWindowEvent
+    {
+        SDL_WINDOWEVENT_NONE,           /* Never used */
+        SDL_WINDOWEVENT_SHOWN,          /* Window has been shown */
+        SDL_WINDOWEVENT_HIDDEN,         /* Window has been hidden */
+        SDL_WINDOWEVENT_EXPOSED,        /* Window has been exposed and should be redrawn */
+        SDL_WINDOWEVENT_MOVED,          /* Window has been moved to data1, data2 */
+        SDL_WINDOWEVENT_RESIZED,        /* Window has been resized to data1xdata2 */
+        SDL_WINDOWEVENT_SIZE_CHANGED,   /* The window size has changed, either as a result of an API call or through the system or user changing the window size. */
+        SDL_WINDOWEVENT_MINIMIZED,      /* Window has been minimized */
+        SDL_WINDOWEVENT_MAXIMIZED,      /* Window has been maximized */
+        SDL_WINDOWEVENT_RESTORED,       /* Window has been restored to normal size and position */
+        SDL_WINDOWEVENT_ENTER,          /* Window has gained mouse focus */
+        SDL_WINDOWEVENT_LEAVE,          /* Window has lost mouse focus */
+        SDL_WINDOWEVENT_FOCUS_GAINED,   /* Window has gained keyboard focus */
+        SDL_WINDOWEVENT_FOCUS_LOST,     /* Window has lost keyboard focus */
+        SDL_WINDOWEVENT_CLOSE           /* The window manager requests that the window be closed */
+    }
+
+    //see SDL_Events.h
+    public enum SdlEventType
+    {
+        SDL_FIRSTEVENT = 0,     /**< Unused (do not remove) */
+
+        /* Application events */
+        SDL_QUIT = 0x100, /**< User-requested quit */
+
+        /* These application events have special meaning on iOS, see README-ios.txt for details */
+        SDL_APP_TERMINATING,        /**< The application is being terminated by the OS
+                                     Called on iOS in applicationWillTerminate()
+                                     Called on Android in onDestroy()
+                                */
+        SDL_APP_LOWMEMORY,          /**< The application is low on memory, free memory if possible.
+                                     Called on iOS in applicationDidReceiveMemoryWarning()
+                                     Called on Android in onLowMemory()
+                                */
+        SDL_APP_WILLENTERBACKGROUND, /**< The application is about to enter the background
+                                     Called on iOS in applicationWillResignActive()
+                                     Called on Android in onPause()
+                                */
+        SDL_APP_DIDENTERBACKGROUND, /**< The application did enter the background and may not get CPU for some time
+                                     Called on iOS in applicationDidEnterBackground()
+                                     Called on Android in onPause()
+                                */
+        SDL_APP_WILLENTERFOREGROUND, /**< The application is about to enter the foreground
+                                     Called on iOS in applicationWillEnterForeground()
+                                     Called on Android in onResume()
+                                */
+        SDL_APP_DIDENTERFOREGROUND, /**< The application is now interactive
+                                     Called on iOS in applicationDidBecomeActive()
+                                     Called on Android in onResume()
+                                */
+
+        /* Window events */
+        SDL_WINDOWEVENT = 0x200, /**< Window state change */
+        SDL_SYSWMEVENT,             /**< System specific event */
+
+        /* Keyboard events */
+        SDL_KEYDOWN = 0x300, /**< Key pressed */
+        SDL_KEYUP,                  /**< Key released */
+        SDL_TEXTEDITING,            /**< Keyboard text editing (composition) */
+        SDL_TEXTINPUT,              /**< Keyboard text input */
+
+        /* Mouse events */
+        SDL_MOUSEMOTION = 0x400, /**< Mouse moved */
+        SDL_MOUSEBUTTONDOWN,        /**< Mouse button pressed */
+        SDL_MOUSEBUTTONUP,          /**< Mouse button released */
+        SDL_MOUSEWHEEL,             /**< Mouse wheel motion */
+
+        /* Joystick events */
+        SDL_JOYAXISMOTION = 0x600, /**< Joystick axis motion */
+        SDL_JOYBALLMOTION,          /**< Joystick trackball motion */
+        SDL_JOYHATMOTION,           /**< Joystick hat position change */
+        SDL_JOYBUTTONDOWN,          /**< Joystick button pressed */
+        SDL_JOYBUTTONUP,            /**< Joystick button released */
+        SDL_JOYDEVICEADDED,         /**< A new joystick has been inserted into the system */
+        SDL_JOYDEVICEREMOVED,       /**< An opened joystick has been removed */
+
+        /* Game controller events */
+        SDL_CONTROLLERAXISMOTION = 0x650, /**< Game controller axis motion */
+        SDL_CONTROLLERBUTTONDOWN,          /**< Game controller button pressed */
+        SDL_CONTROLLERBUTTONUP,            /**< Game controller button released */
+        SDL_CONTROLLERDEVICEADDED,         /**< A new Game controller has been inserted into the system */
+        SDL_CONTROLLERDEVICEREMOVED,       /**< An opened Game controller has been removed */
+        SDL_CONTROLLERDEVICEREMAPPED,      /**< The controller mapping was updated */
+
+        /* Touch events */
+        SDL_FINGERDOWN = 0x700,
+        SDL_FINGERUP,
+        SDL_FINGERMOTION,
+
+        /* Gesture events */
+        SDL_DOLLARGESTURE = 0x800,
+        SDL_DOLLARRECORD,
+        SDL_MULTIGESTURE,
+
+        /* Clipboard events */
+        SDL_CLIPBOARDUPDATE = 0x900, /**< The clipboard changed */
+
+        /* Drag and drop events */
+        SDL_DROPFILE = 0x1000, /**< The system requests a file open */
+
+        /* Render events */
+        SDL_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset */
+
+        /** Events ::SDL_USEREVENT through ::SDL_LASTEVENT are for your use,
+         *  and should be allocated with SDL_RegisterEvents()
+         */
+        SDL_USEREVENT = 0x8000,
+
+        /**
+         *  This last event is only for bounding internal arrays
+         */
+        SDL_LASTEVENT = 0xFFFF
+    }
+}

+ 8 - 0
Script/AtomicNET/AtomicNET/Graphics/Graphics.cs

@@ -8,6 +8,14 @@ namespace AtomicEngine
     public partial class Graphics : AObject
     {
 
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        static extern IntPtr csi_Atomic_Graphics_GetSDLWindow();
+
+        /// <summary>
+        /// Pointer to SDL window
+        /// </summary>
+        public IntPtr SDLWindow => csi_Atomic_Graphics_GetSDLWindow();
+
         // Shader Parameters
 
         public void SetShaderParameter(string param, Matrix3x4 matrix)

+ 914 - 914
Script/AtomicNET/AtomicNET/Math/IntVector2.cs

@@ -26,918 +26,918 @@ using System;
 using System.Runtime.InteropServices;
 namespace AtomicEngine
 {
-	/// <summary>Represents a 2D vector using two single-precision inting-point numbers.</summary>
-	/// <remarks>
-	/// The IntVector2 structure is suitable for interoperation with unmanaged code requiring two consecutive ints.
-	/// </remarks>
-	[StructLayout(LayoutKind.Sequential)]
-	public struct IntVector2 : IEquatable<IntVector2>
-	{
-		#region Fields
-
-		/// <summary>
-		/// The X component of the IntVector2.
-		/// </summary>
-		public int X;
-
-		/// <summary>
-		/// The Y component of the IntVector2.
-		/// </summary>
-		public int Y;
-
-		#endregion
-
-		#region Constructors
-
-		/// <summary>
-		/// Constructs a new IntVector2.
-		/// </summary>
-		/// <param name="x">The x coordinate of the net IntVector2.</param>
-		/// <param name="y">The y coordinate of the net IntVector2.</param>
-		public IntVector2(int x, int y)
-		{
-			X = x;
-			Y = y;
-		}
-
-		/// <summary>
-		/// Constructs a new IntVector2 from the given IntVector2.
-		/// </summary>
-		/// <param name="v">The IntVector2 to copy components from.</param>
-		[Obsolete]
-		public IntVector2(IntVector2 v)
-		{
-			X = v.X;
-			Y = v.Y;
-		}
-
-		/// <summary>
-		/// Constructs a new IntVector2 from the given Vector2.
-		/// </summary>
-		/// <param name="v">The IntVector2 to copy components from.</param>
-		[Obsolete]
-		public IntVector2(Vector2 v)
-		{
-			X = (int) v.X;
-			Y = (int) v.Y;
-		}
-
-		#endregion
-
-		#region Public Members
-
-		#region Instance
-
-		#region public void Add()
-
-		/// <summary>Add the Vector passed as parameter to this instance.</summary>
-		/// <param name="right">Right operand. This parameter is only read from.</param>
-		[Obsolete("Use static Add() method instead.")]
-		public void Add(IntVector2 right)
-		{
-			this.X += right.X;
-			this.Y += right.Y;
-		}
-
-		/// <summary>Add the Vector passed as parameter to this instance.</summary>
-		/// <param name="right">Right operand. This parameter is only read from.</param>
-		[CLSCompliant(false)]
-		[Obsolete("Use static Add() method instead.")]
-		public void Add(ref IntVector2 right)
-		{
-			this.X += right.X;
-			this.Y += right.Y;
-		}
-
-		#endregion public void Add()
-
-		#region public void Sub()
-
-		/// <summary>Subtract the Vector passed as parameter from this instance.</summary>
-		/// <param name="right">Right operand. This parameter is only read from.</param>
-		[Obsolete("Use static Subtract() method instead.")]
-		public void Sub(IntVector2 right)
-		{
-			this.X -= right.X;
-			this.Y -= right.Y;
-		}
-
-		/// <summary>Subtract the Vector passed as parameter from this instance.</summary>
-		/// <param name="right">Right operand. This parameter is only read from.</param>
-		[CLSCompliant(false)]
-		[Obsolete("Use static Subtract() method instead.")]
-		public void Sub(ref IntVector2 right)
-		{
-			this.X -= right.X;
-			this.Y -= right.Y;
-		}
-
-		#endregion public void Sub()
-
-		#region public void Mult()
-
-		/// <summary>Multiply this instance by a scalar.</summary>
-		/// <param name="f">Scalar operand.</param>
-		[Obsolete("Use static Multiply() method instead.")]
-		public void Mult(int f)
-		{
-			this.X *= f;
-			this.Y *= f;
-		}
-
-		#endregion public void Mult()
-
-		#region public void Div()
-
-		/// <summary>Divide this instance by a scalar.</summary>
-		/// <param name="f">Scalar operand.</param>
-		[Obsolete("Use static Divide() method instead.")]
-		public void Div(int f)
-		{
-			this.X =  X / f;
-			this.Y = Y / f;
-		}
-
-		#endregion public void Div()
-
-		#region public int Length
-
-		/// <summary>
-		/// Gets the length (magnitude) of the vector.
-		/// </summary>
-		/// <see cref="LengthFast"/>
-		/// <seealso cref="LengthSquared"/>
-		public int Length
-		{
-			get
-			{
-				return (int)System.Math.Sqrt(X * X + Y * Y);
-			}
-		}
-
-		#endregion
-
-		#region public int LengthFast
-
-		/// <summary>
-		/// Gets an approximation of the vector length (magnitude).
-		/// </summary>
-		/// <remarks>
-		/// This property uses an approximation of the square root function to calculate vector magnitude, with
-		/// an upper error bound of 0.001.
-		/// </remarks>
-		/// <see cref="Length"/>
-		/// <seealso cref="LengthSquared"/>
-		public int LengthFast
-		{
-			get
-			{
-				return (int) (1.0f / MathHelper.InverseSqrtFast(X * X + Y * Y));
-			}
-		}
-
-		#endregion
-
-		#region public int LengthSquared
-
-		/// <summary>
-		/// Gets the square of the vector length (magnitude).
-		/// </summary>
-		/// <remarks>
-		/// This property avoids the costly square root operation required by the Length property. This makes it more suitable
-		/// for comparisons.
-		/// </remarks>
-		/// <see cref="Length"/>
-		/// <seealso cref="LengthFast"/>
-		public int LengthSquared
-		{
-			get
-			{
-				return X * X + Y * Y;
-			}
-		}
-
-		#endregion
-
-		#region public IntVector2 PerpendicularRight
-
-		/// <summary>
-		/// Gets the perpendicular vector on the right side of this vector.
-		/// </summary>
-		public IntVector2 PerpendicularRight
-		{
-			get
-			{
-				return new IntVector2(Y, -X);
-			}
-		}
-
-		#endregion
-
-		#region public IntVector2 PerpendicularLeft
-
-		/// <summary>
-		/// Gets the perpendicular vector on the left side of this vector.
-		/// </summary>
-		public IntVector2 PerpendicularLeft
-		{
-			get
-			{
-				return new IntVector2(-Y, X);
-			}
-		}
-
-		#endregion
-
-		#region public void Normalize()
-
-		/// <summary>
-		/// Scales the IntVector2 to unit length.
-		/// </summary>
-		public void Normalize()
-		{
-			X =  X / this.Length;
-			Y *= Y / this.Length;
-		}
-
-		#endregion
-
-		#region public void NormalizeFast()
-
-		/// <summary>
-		/// Scales the IntVector2 to approximately unit length.
-		/// </summary>
-		public void NormalizeFast()
-		{
-			int scale = (int) MathHelper.InverseSqrtFast(X * X + Y * Y);
-			X *= scale;
-			Y *= scale;
-		}
-
-		#endregion
-
-		#region public void Scale()
-
-		/// <summary>
-		/// Scales the current IntVector2 by the given amounts.
-		/// </summary>
-		/// <param name="sx">The scale of the X component.</param>
-		/// <param name="sy">The scale of the Y component.</param>
-		[Obsolete("Use static Multiply() method instead.")]
-		public void Scale(int sx, int sy)
-		{
-			this.X = X * sx;
-			this.Y = Y * sy;
-		}
-
-		/// <summary>Scales this instance by the given parameter.</summary>
-		/// <param name="scale">The scaling of the individual components.</param>
-		[Obsolete("Use static Multiply() method instead.")]
-		public void Scale(IntVector2 scale)
-		{
-			this.X *= scale.X;
-			this.Y *= scale.Y;
-		}
-
-		/// <summary>Scales this instance by the given parameter.</summary>
-		/// <param name="scale">The scaling of the individual components.</param>
-		[CLSCompliant(false)]
-		[Obsolete("Use static Multiply() method instead.")]
-		public void Scale(ref IntVector2 scale)
-		{
-			this.X *= scale.X;
-			this.Y *= scale.Y;
-		}
-
-		#endregion public void Scale()
-
-		#endregion
-
-		#region Static
-
-		#region Fields
-
-		/// <summary>
-		/// Defines a unit-length IntVector2 that points towards the X-axis.
-		/// </summary>
-		public static readonly IntVector2 UnitX = new IntVector2(1, 0);
-
-		/// <summary>
-		/// Defines a unit-length IntVector2 that points towards the Y-axis.
-		/// </summary>
-		public static readonly IntVector2 UnitY = new IntVector2(0, 1);
-
-		/// <summary>
-		/// Defines a zero-length IntVector2.
-		/// </summary>
-		public static readonly IntVector2 Zero = new IntVector2(0, 0);
-
-		/// <summary>
-		/// Defines an instance with all components set to 1.
-		/// </summary>
-		public static readonly IntVector2 One = new IntVector2(1, 1);
-
-		/// <summary>
-		/// Defines the size of the IntVector2 struct in bytes.
-		/// </summary>
-		public static readonly int SizeInBytes = Marshal.SizeOf(new IntVector2());
-
-		#endregion
-
-		#region Add
-
-		/// <summary>
-		/// Adds two vectors.
-		/// </summary>
-		/// <param name="a">Left operand.</param>
-		/// <param name="b">Right operand.</param>
-		/// <returns>Result of operation.</returns>
-		public static IntVector2 Add(IntVector2 a, IntVector2 b)
-		{
-			Add(ref a, ref b, out a);
-			return a;
-		}
-
-		/// <summary>
-		/// Adds two vectors.
-		/// </summary>
-		/// <param name="a">Left operand.</param>
-		/// <param name="b">Right operand.</param>
-		/// <param name="result">Result of operation.</param>
-		public static void Add(ref IntVector2 a, ref IntVector2 b, out IntVector2 result)
-		{
-			result = new IntVector2(a.X + b.X, a.Y + b.Y);
-		}
-
-		#endregion
-
-		#region Subtract
-
-		/// <summary>
-		/// Subtract one Vector from another
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <returns>Result of subtraction</returns>
-		public static IntVector2 Subtract(IntVector2 a, IntVector2 b)
-		{
-			Subtract(ref a, ref b, out a);
-			return a;
-		}
-
-		/// <summary>
-		/// Subtract one Vector from another
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <param name="result">Result of subtraction</param>
-		public static void Subtract(ref IntVector2 a, ref IntVector2 b, out IntVector2 result)
-		{
-			result = new IntVector2(a.X - b.X, a.Y - b.Y);
-		}
-
-		#endregion
-
-		#region Multiply
-
-		/// <summary>
-		/// Multiplies a vector by a scalar.
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of the operation.</returns>
-		public static IntVector2 Multiply(IntVector2 vector, int scale)
-		{
-			Multiply(ref vector, scale, out vector);
-			return vector;
-		}
-
-		/// <summary>
-		/// Multiplies a vector by a scalar.
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <param name="result">Result of the operation.</param>
-		public static void Multiply(ref IntVector2 vector, int scale, out IntVector2 result)
-		{
-			result = new IntVector2(vector.X * scale, vector.Y * scale);
-		}
-
-		/// <summary>
-		/// Multiplies a vector by the components a vector (scale).
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of the operation.</returns>
-		public static IntVector2 Multiply(IntVector2 vector, IntVector2 scale)
-		{
-			Multiply(ref vector, ref scale, out vector);
-			return vector;
-		}
-
-		/// <summary>
-		/// Multiplies a vector by the components of a vector (scale).
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <param name="result">Result of the operation.</param>
-		public static void Multiply(ref IntVector2 vector, ref IntVector2 scale, out IntVector2 result)
-		{
-			result = new IntVector2(vector.X * scale.X, vector.Y * scale.Y);
-		}
-
-		#endregion
-
-		#region Divide
-
-		/// <summary>
-		/// Divides a vector by a scalar.
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of the operation.</returns>
-		public static IntVector2 Divide(IntVector2 vector, int scale)
-		{
-			Divide(ref vector, scale, out vector);
-			return vector;
-		}
-
-		/// <summary>
-		/// Divides a vector by a scalar.
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <param name="result">Result of the operation.</param>
-		public static void Divide(ref IntVector2 vector, int scale, out IntVector2 result)
-		{
-			Multiply(ref vector, 1 / scale, out result);
-		}
-
-		/// <summary>
-		/// Divides a vector by the components of a vector (scale).
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of the operation.</returns>
-		public static IntVector2 Divide(IntVector2 vector, IntVector2 scale)
-		{
-			Divide(ref vector, ref scale, out vector);
-			return vector;
-		}
-
-		/// <summary>
-		/// Divide a vector by the components of a vector (scale).
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <param name="result">Result of the operation.</param>
-		public static void Divide(ref IntVector2 vector, ref IntVector2 scale, out IntVector2 result)
-		{
-			result = new IntVector2(vector.X / scale.X, vector.Y / scale.Y);
-		}
-
-		#endregion
-
-		#region ComponentMin
-
-		/// <summary>
-		/// Calculate the component-wise minimum of two vectors
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <returns>The component-wise minimum</returns>
-		public static IntVector2 ComponentMin(IntVector2 a, IntVector2 b)
-		{
-			a.X = a.X < b.X ? a.X : b.X;
-			a.Y = a.Y < b.Y ? a.Y : b.Y;
-			return a;
-		}
-
-		/// <summary>
-		/// Calculate the component-wise minimum of two vectors
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <param name="result">The component-wise minimum</param>
-		public static void ComponentMin(ref IntVector2 a, ref IntVector2 b, out IntVector2 result)
-		{
-			result.X = a.X < b.X ? a.X : b.X;
-			result.Y = a.Y < b.Y ? a.Y : b.Y;
-		}
-
-		#endregion
-
-		#region ComponentMax
-
-		/// <summary>
-		/// Calculate the component-wise maximum of two vectors
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <returns>The component-wise maximum</returns>
-		public static IntVector2 ComponentMax(IntVector2 a, IntVector2 b)
-		{
-			a.X = a.X > b.X ? a.X : b.X;
-			a.Y = a.Y > b.Y ? a.Y : b.Y;
-			return a;
-		}
-
-		/// <summary>
-		/// Calculate the component-wise maximum of two vectors
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <param name="result">The component-wise maximum</param>
-		public static void ComponentMax(ref IntVector2 a, ref IntVector2 b, out IntVector2 result)
-		{
-			result.X = a.X > b.X ? a.X : b.X;
-			result.Y = a.Y > b.Y ? a.Y : b.Y;
-		}
-
-		#endregion
-
-		#region Min
-
-		/// <summary>
-		/// Returns the Vector3 with the minimum magnitude
-		/// </summary>
-		/// <param name="left">Left operand</param>
-		/// <param name="right">Right operand</param>
-		/// <returns>The minimum Vector3</returns>
-		public static IntVector2 Min(IntVector2 left, IntVector2 right)
-		{
-			return left.LengthSquared < right.LengthSquared ? left : right;
-		}
-
-		#endregion
-
-		#region Max
-
-		/// <summary>
-		/// Returns the Vector3 with the minimum magnitude
-		/// </summary>
-		/// <param name="left">Left operand</param>
-		/// <param name="right">Right operand</param>
-		/// <returns>The minimum Vector3</returns>
-		public static IntVector2 Max(IntVector2 left, IntVector2 right)
-		{
-			return left.LengthSquared >= right.LengthSquared ? left : right;
-		}
-
-		#endregion
-
-		#region Clamp
-
-		/// <summary>
-		/// Clamp a vector to the given minimum and maximum vectors
-		/// </summary>
-		/// <param name="vec">Input vector</param>
-		/// <param name="min">Minimum vector</param>
-		/// <param name="max">Maximum vector</param>
-		/// <returns>The clamped vector</returns>
-		public static IntVector2 Clamp(IntVector2 vec, IntVector2 min, IntVector2 max)
-		{
-			vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
-			vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
-			return vec;
-		}
-
-		/// <summary>
-		/// Clamp a vector to the given minimum and maximum vectors
-		/// </summary>
-		/// <param name="vec">Input vector</param>
-		/// <param name="min">Minimum vector</param>
-		/// <param name="max">Maximum vector</param>
-		/// <param name="result">The clamped vector</param>
-		public static void Clamp(ref IntVector2 vec, ref IntVector2 min, ref IntVector2 max, out IntVector2 result)
-		{
-			result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
-			result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
-		}
-
-		#endregion
-
-		#region Normalize
-
-		/// <summary>
-		/// Scale a vector to unit length
-		/// </summary>
-		/// <param name="vec">The input vector</param>
-		/// <returns>The normalized vector</returns>
-		public static IntVector2 Normalize(IntVector2 vec)
-		{
-			vec.X = vec.X / vec.Length;
-			vec.Y = vec.Y / vec.Length;
-			return vec;
-		}
-
-		/// <summary>
-		/// Scale a vector to unit length
-		/// </summary>
-		/// <param name="vec">The input vector</param>
-		/// <param name="result">The normalized vector</param>
-		public static void Normalize(ref IntVector2 vec, out IntVector2 result)
-		{
-			result.X = vec.X / vec.Length;
-			result.Y = vec.Y / vec.Length;
-		}
-
-		#endregion
-
-		#region NormalizeFast
-
-		/// <summary>
-		/// Scale a vector to approximately unit length
-		/// </summary>
-		/// <param name="vec">The input vector</param>
-		/// <returns>The normalized vector</returns>
-		public static IntVector2 NormalizeFast(IntVector2 vec)
-		{
-			int scale = (int) MathHelper.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
-			vec.X *= scale;
-			vec.Y *= scale;
-			return vec;
-		}
-
-		/// <summary>
-		/// Scale a vector to approximately unit length
-		/// </summary>
-		/// <param name="vec">The input vector</param>
-		/// <param name="result">The normalized vector</param>
-		public static void NormalizeFast(ref IntVector2 vec, out IntVector2 result)
-		{
-			int scale = (int) MathHelper.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
-			result.X = vec.X * scale;
-			result.Y = vec.Y * scale;
-		}
-
-		#endregion
-
-		#region Dot
-
-		/// <summary>
-		/// Calculate the dot (scalar) product of two vectors
-		/// </summary>
-		/// <param name="left">First operand</param>
-		/// <param name="right">Second operand</param>
-		/// <returns>The dot product of the two inputs</returns>
-		public static int Dot(IntVector2 left, IntVector2 right)
-		{
-			return left.X * right.X + left.Y * right.Y;
-		}
-
-		/// <summary>
-		/// Calculate the dot (scalar) product of two vectors
-		/// </summary>
-		/// <param name="left">First operand</param>
-		/// <param name="right">Second operand</param>
-		/// <param name="result">The dot product of the two inputs</param>
-		public static void Dot(ref IntVector2 left, ref IntVector2 right, out int result)
-		{
-			result = left.X * right.X + left.Y * right.Y;
-		}
-
-		#endregion
-
-		#region Lerp
-
-		/// <summary>
-		/// Returns a new Vector that is the linear blend of the 2 given Vectors
-		/// </summary>
-		/// <param name="a">First input vector</param>
-		/// <param name="b">Second input vector</param>
-		/// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
-		/// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
-		public static IntVector2 Lerp(IntVector2 a, IntVector2 b, int blend)
-		{
-			a.X = blend * (b.X - a.X) + a.X;
-			a.Y = blend * (b.Y - a.Y) + a.Y;
-			return a;
-		}
-
-		/// <summary>
-		/// Returns a new Vector that is the linear blend of the 2 given Vectors
-		/// </summary>
-		/// <param name="a">First input vector</param>
-		/// <param name="b">Second input vector</param>
-		/// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
-		/// <param name="result">a when blend=0, b when blend=1, and a linear combination otherwise</param>
-		public static void Lerp(ref IntVector2 a, ref IntVector2 b, int blend, out IntVector2 result)
-		{
-			result.X = blend * (b.X - a.X) + a.X;
-			result.Y = blend * (b.Y - a.Y) + a.Y;
-		}
-
-		#endregion
-
-		#region Barycentric
-
-		/// <summary>
-		/// Interpolate 3 Vectors using Barycentric coordinates
-		/// </summary>
-		/// <param name="a">First input Vector</param>
-		/// <param name="b">Second input Vector</param>
-		/// <param name="c">Third input Vector</param>
-		/// <param name="u">First Barycentric Coordinate</param>
-		/// <param name="v">Second Barycentric Coordinate</param>
-		/// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
-		public static IntVector2 BaryCentric(IntVector2 a, IntVector2 b, IntVector2 c, int u, int v)
-		{
-			return a + u * (b - a) + v * (c - a);
-		}
-
-		/// <summary>Interpolate 3 Vectors using Barycentric coordinates</summary>
-		/// <param name="a">First input Vector.</param>
-		/// <param name="b">Second input Vector.</param>
-		/// <param name="c">Third input Vector.</param>
-		/// <param name="u">First Barycentric Coordinate.</param>
-		/// <param name="v">Second Barycentric Coordinate.</param>
-		/// <param name="result">Output Vector. a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</param>
-		public static void BaryCentric(ref IntVector2 a, ref IntVector2 b, ref IntVector2 c, int u, int v, out IntVector2 result)
-		{
-			result = a; // copy
-
-			IntVector2 temp = b; // copy
-			Subtract(ref temp, ref a, out temp);
-			Multiply(ref temp, u, out temp);
-			Add(ref result, ref temp, out result);
-
-			temp = c; // copy
-			Subtract(ref temp, ref a, out temp);
-			Multiply(ref temp, v, out temp);
-			Add(ref result, ref temp, out result);
-		}
-
-		#endregion
-
-		#endregion
-
-		#region Operators
-
-		/// <summary>
-		/// Adds the specified instances.
-		/// </summary>
-		/// <param name="left">Left operand.</param>
-		/// <param name="right">Right operand.</param>
-		/// <returns>Result of addition.</returns>
-		public static IntVector2 operator +(IntVector2 left, IntVector2 right)
-		{
-			left.X += right.X;
-			left.Y += right.Y;
-			return left;
-		}
-
-		/// <summary>
-		/// Subtracts the specified instances.
-		/// </summary>
-		/// <param name="left">Left operand.</param>
-		/// <param name="right">Right operand.</param>
-		/// <returns>Result of subtraction.</returns>
-		public static IntVector2 operator -(IntVector2 left, IntVector2 right)
-		{
-			left.X -= right.X;
-			left.Y -= right.Y;
-			return left;
-		}
-
-		/// <summary>
-		/// Negates the specified instance.
-		/// </summary>
-		/// <param name="vec">Operand.</param>
-		/// <returns>Result of negation.</returns>
-		public static IntVector2 operator -(IntVector2 vec)
-		{
-			vec.X = -vec.X;
-			vec.Y = -vec.Y;
-			return vec;
-		}
-
-		/// <summary>
-		/// Multiplies the specified instance by a scalar.
-		/// </summary>
-		/// <param name="vec">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of multiplication.</returns>
-		public static IntVector2 operator *(IntVector2 vec, int scale)
-		{
-			vec.X *= scale;
-			vec.Y *= scale;
-			return vec;
-		}
-
-		/// <summary>
-		/// Multiplies the specified instance by a scalar.
-		/// </summary>
-		/// <param name="scale">Left operand.</param>
-		/// <param name="vec">Right operand.</param>
-		/// <returns>Result of multiplication.</returns>
-		public static IntVector2 operator *(int scale, IntVector2 vec)
-		{
-			vec.X *= scale;
-			vec.Y *= scale;
-			return vec;
-		}
-
-		/// <summary>
-		/// Divides the specified instance by a scalar.
-		/// </summary>
-		/// <param name="vec">Left operand</param>
-		/// <param name="scale">Right operand</param>
-		/// <returns>Result of the division.</returns>
-		public static IntVector2 operator /(IntVector2 vec, int scale)
-		{
-			vec.X = vec.X / scale;
-			vec.Y = vec.Y / scale;
-			return vec;
-		}
-
-		/// <summary>
-		/// Compares the specified instances for equality.
-		/// </summary>
-		/// <param name="left">Left operand.</param>
-		/// <param name="right">Right operand.</param>
-		/// <returns>True if both instances are equal; false otherwise.</returns>
-		public static bool operator ==(IntVector2 left, IntVector2 right)
-		{
-			return left.Equals(right);
-		}
-
-		/// <summary>
-		/// Compares the specified instances for inequality.
-		/// </summary>
-		/// <param name="left">Left operand.</param>
-		/// <param name="right">Right operand.</param>
-		/// <returns>True if both instances are not equal; false otherwise.</returns>
-		public static bool operator !=(IntVector2 left, IntVector2 right)
-		{
-			return !left.Equals(right);
-		}
-
-		#endregion
-
-		#region Overrides
-
-		#region public override string ToString()
-
-		/// <summary>
-		/// Returns a System.String that represents the current IntVector2.
-		/// </summary>
-		/// <returns></returns>
-		public override string ToString()
-		{
-			return String.Format("({0}, {1})", X, Y);
-		}
-
-		#endregion
-
-		#region public override int GetHashCode()
-
-		/// <summary>
-		/// Returns the hashcode for this instance.
-		/// </summary>
-		/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
-		public override int GetHashCode()
-		{
-			return X.GetHashCode() ^ Y.GetHashCode();
-		}
-
-		#endregion
-
-		#region public override bool Equals(object obj)
-
-		/// <summary>
-		/// Indicates whether this instance and a specified object are equal.
-		/// </summary>
-		/// <param name="obj">The object to compare to.</param>
-		/// <returns>True if the instances are equal; false otherwise.</returns>
-		public override bool Equals(object obj)
-		{
-			if (!(obj is IntVector2))
-				return false;
-
-			return this.Equals((IntVector2)obj);
-		}
-
-		#endregion
-
-		#endregion
-
-		#endregion
-
-		#region IEquatable<IntVector2> Members
-
-		/// <summary>Indicates whether the current vector is equal to another vector.</summary>
-		/// <param name="other">A vector to compare with this vector.</param>
-		/// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
-		public bool Equals(IntVector2 other)
-		{
-			return
-				X == other.X &&
-				Y == other.Y;
-		}
-
-		#endregion
-
-		public bool IsEmpty => X == 0 && Y == 0;
-	}
+    /// <summary>Represents a 2D vector using two single-precision inting-point numbers.</summary>
+    /// <remarks>
+    /// The IntVector2 structure is suitable for interoperation with unmanaged code requiring two consecutive ints.
+    /// </remarks>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct IntVector2 : IEquatable<IntVector2>
+    {
+        #region Fields
+
+        /// <summary>
+        /// The X component of the IntVector2.
+        /// </summary>
+        public int X;
+
+        /// <summary>
+        /// The Y component of the IntVector2.
+        /// </summary>
+        public int Y;
+
+        #endregion
+
+        #region Constructors
+
+        /// <summary>
+        /// Constructs a new IntVector2.
+        /// </summary>
+        /// <param name="x">The x coordinate of the net IntVector2.</param>
+        /// <param name="y">The y coordinate of the net IntVector2.</param>
+        public IntVector2(int x, int y)
+        {
+            X = x;
+            Y = y;
+        }
+
+        /// <summary>
+        /// Constructs a new IntVector2 from the given IntVector2.
+        /// </summary>
+        /// <param name="v">The IntVector2 to copy components from.</param>
+        [Obsolete]
+        public IntVector2(IntVector2 v)
+        {
+            X = v.X;
+            Y = v.Y;
+        }
+
+        /// <summary>
+        /// Constructs a new IntVector2 from the given Vector2.
+        /// </summary>
+        /// <param name="v">The IntVector2 to copy components from.</param>
+        [Obsolete]
+        public IntVector2(Vector2 v)
+        {
+            X = (int) v.X;
+            Y = (int) v.Y;
+        }
+
+        #endregion
+
+        #region Public Members
+
+        #region Instance
+
+        #region public void Add()
+
+        /// <summary>Add the Vector passed as parameter to this instance.</summary>
+        /// <param name="right">Right operand. This parameter is only read from.</param>
+        [Obsolete("Use static Add() method instead.")]
+        public void Add(IntVector2 right)
+        {
+            this.X += right.X;
+            this.Y += right.Y;
+        }
+
+        /// <summary>Add the Vector passed as parameter to this instance.</summary>
+        /// <param name="right">Right operand. This parameter is only read from.</param>
+        [CLSCompliant(false)]
+        [Obsolete("Use static Add() method instead.")]
+        public void Add(ref IntVector2 right)
+        {
+            this.X += right.X;
+            this.Y += right.Y;
+        }
+
+        #endregion public void Add()
+
+        #region public void Sub()
+
+        /// <summary>Subtract the Vector passed as parameter from this instance.</summary>
+        /// <param name="right">Right operand. This parameter is only read from.</param>
+        [Obsolete("Use static Subtract() method instead.")]
+        public void Sub(IntVector2 right)
+        {
+            this.X -= right.X;
+            this.Y -= right.Y;
+        }
+
+        /// <summary>Subtract the Vector passed as parameter from this instance.</summary>
+        /// <param name="right">Right operand. This parameter is only read from.</param>
+        [CLSCompliant(false)]
+        [Obsolete("Use static Subtract() method instead.")]
+        public void Sub(ref IntVector2 right)
+        {
+            this.X -= right.X;
+            this.Y -= right.Y;
+        }
+
+        #endregion public void Sub()
+
+        #region public void Mult()
+
+        /// <summary>Multiply this instance by a scalar.</summary>
+        /// <param name="f">Scalar operand.</param>
+        [Obsolete("Use static Multiply() method instead.")]
+        public void Mult(int f)
+        {
+            this.X *= f;
+            this.Y *= f;
+        }
+
+        #endregion public void Mult()
+
+        #region public void Div()
+
+        /// <summary>Divide this instance by a scalar.</summary>
+        /// <param name="f">Scalar operand.</param>
+        [Obsolete("Use static Divide() method instead.")]
+        public void Div(int f)
+        {
+            this.X =  X / f;
+            this.Y = Y / f;
+        }
+
+        #endregion public void Div()
+
+        #region public int Length
+
+        /// <summary>
+        /// Gets the length (magnitude) of the vector.
+        /// </summary>
+        /// <see cref="LengthFast"/>
+        /// <seealso cref="LengthSquared"/>
+        public int Length
+        {
+            get
+            {
+                return (int)System.Math.Sqrt(X * X + Y * Y);
+            }
+        }
+
+        #endregion
+
+        #region public int LengthFast
+
+        /// <summary>
+        /// Gets an approximation of the vector length (magnitude).
+        /// </summary>
+        /// <remarks>
+        /// This property uses an approximation of the square root function to calculate vector magnitude, with
+        /// an upper error bound of 0.001.
+        /// </remarks>
+        /// <see cref="Length"/>
+        /// <seealso cref="LengthSquared"/>
+        public int LengthFast
+        {
+            get
+            {
+                return (int) (1.0f / MathHelper.InverseSqrtFast(X * X + Y * Y));
+            }
+        }
+
+        #endregion
+
+        #region public int LengthSquared
+
+        /// <summary>
+        /// Gets the square of the vector length (magnitude).
+        /// </summary>
+        /// <remarks>
+        /// This property avoids the costly square root operation required by the Length property. This makes it more suitable
+        /// for comparisons.
+        /// </remarks>
+        /// <see cref="Length"/>
+        /// <seealso cref="LengthFast"/>
+        public int LengthSquared
+        {
+            get
+            {
+                return X * X + Y * Y;
+            }
+        }
+
+        #endregion
+
+        #region public IntVector2 PerpendicularRight
+
+        /// <summary>
+        /// Gets the perpendicular vector on the right side of this vector.
+        /// </summary>
+        public IntVector2 PerpendicularRight
+        {
+            get
+            {
+                return new IntVector2(Y, -X);
+            }
+        }
+
+        #endregion
+
+        #region public IntVector2 PerpendicularLeft
+
+        /// <summary>
+        /// Gets the perpendicular vector on the left side of this vector.
+        /// </summary>
+        public IntVector2 PerpendicularLeft
+        {
+            get
+            {
+                return new IntVector2(-Y, X);
+            }
+        }
+
+        #endregion
+
+        #region public void Normalize()
+
+        /// <summary>
+        /// Scales the IntVector2 to unit length.
+        /// </summary>
+        public void Normalize()
+        {
+            X =  X / this.Length;
+            Y *= Y / this.Length;
+        }
+
+        #endregion
+
+        #region public void NormalizeFast()
+
+        /// <summary>
+        /// Scales the IntVector2 to approximately unit length.
+        /// </summary>
+        public void NormalizeFast()
+        {
+            int scale = (int) MathHelper.InverseSqrtFast(X * X + Y * Y);
+            X *= scale;
+            Y *= scale;
+        }
+
+        #endregion
+
+        #region public void Scale()
+
+        /// <summary>
+        /// Scales the current IntVector2 by the given amounts.
+        /// </summary>
+        /// <param name="sx">The scale of the X component.</param>
+        /// <param name="sy">The scale of the Y component.</param>
+        [Obsolete("Use static Multiply() method instead.")]
+        public void Scale(int sx, int sy)
+        {
+            this.X = X * sx;
+            this.Y = Y * sy;
+        }
+
+        /// <summary>Scales this instance by the given parameter.</summary>
+        /// <param name="scale">The scaling of the individual components.</param>
+        [Obsolete("Use static Multiply() method instead.")]
+        public void Scale(IntVector2 scale)
+        {
+            this.X *= scale.X;
+            this.Y *= scale.Y;
+        }
+
+        /// <summary>Scales this instance by the given parameter.</summary>
+        /// <param name="scale">The scaling of the individual components.</param>
+        [CLSCompliant(false)]
+        [Obsolete("Use static Multiply() method instead.")]
+        public void Scale(ref IntVector2 scale)
+        {
+            this.X *= scale.X;
+            this.Y *= scale.Y;
+        }
+
+        #endregion public void Scale()
+
+        #endregion
+
+        #region Static
+
+        #region Fields
+
+        /// <summary>
+        /// Defines a unit-length IntVector2 that points towards the X-axis.
+        /// </summary>
+        public static readonly IntVector2 UnitX = new IntVector2(1, 0);
+
+        /// <summary>
+        /// Defines a unit-length IntVector2 that points towards the Y-axis.
+        /// </summary>
+        public static readonly IntVector2 UnitY = new IntVector2(0, 1);
+
+        /// <summary>
+        /// Defines a zero-length IntVector2.
+        /// </summary>
+        public static readonly IntVector2 Zero = new IntVector2(0, 0);
+
+        /// <summary>
+        /// Defines an instance with all components set to 1.
+        /// </summary>
+        public static readonly IntVector2 One = new IntVector2(1, 1);
+
+        /// <summary>
+        /// Defines the size of the IntVector2 struct in bytes.
+        /// </summary>
+        public static readonly int SizeInBytes = Marshal.SizeOf(new IntVector2());
+
+        #endregion
+
+        #region Add
+
+        /// <summary>
+        /// Adds two vectors.
+        /// </summary>
+        /// <param name="a">Left operand.</param>
+        /// <param name="b">Right operand.</param>
+        /// <returns>Result of operation.</returns>
+        public static IntVector2 Add(IntVector2 a, IntVector2 b)
+        {
+            Add(ref a, ref b, out a);
+            return a;
+        }
+
+        /// <summary>
+        /// Adds two vectors.
+        /// </summary>
+        /// <param name="a">Left operand.</param>
+        /// <param name="b">Right operand.</param>
+        /// <param name="result">Result of operation.</param>
+        public static void Add(ref IntVector2 a, ref IntVector2 b, out IntVector2 result)
+        {
+            result = new IntVector2(a.X + b.X, a.Y + b.Y);
+        }
+
+        #endregion
+
+        #region Subtract
+
+        /// <summary>
+        /// Subtract one Vector from another
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <returns>Result of subtraction</returns>
+        public static IntVector2 Subtract(IntVector2 a, IntVector2 b)
+        {
+            Subtract(ref a, ref b, out a);
+            return a;
+        }
+
+        /// <summary>
+        /// Subtract one Vector from another
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <param name="result">Result of subtraction</param>
+        public static void Subtract(ref IntVector2 a, ref IntVector2 b, out IntVector2 result)
+        {
+            result = new IntVector2(a.X - b.X, a.Y - b.Y);
+        }
+
+        #endregion
+
+        #region Multiply
+
+        /// <summary>
+        /// Multiplies a vector by a scalar.
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of the operation.</returns>
+        public static IntVector2 Multiply(IntVector2 vector, int scale)
+        {
+            Multiply(ref vector, scale, out vector);
+            return vector;
+        }
+
+        /// <summary>
+        /// Multiplies a vector by a scalar.
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <param name="result">Result of the operation.</param>
+        public static void Multiply(ref IntVector2 vector, int scale, out IntVector2 result)
+        {
+            result = new IntVector2(vector.X * scale, vector.Y * scale);
+        }
+
+        /// <summary>
+        /// Multiplies a vector by the components a vector (scale).
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of the operation.</returns>
+        public static IntVector2 Multiply(IntVector2 vector, IntVector2 scale)
+        {
+            Multiply(ref vector, ref scale, out vector);
+            return vector;
+        }
+
+        /// <summary>
+        /// Multiplies a vector by the components of a vector (scale).
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <param name="result">Result of the operation.</param>
+        public static void Multiply(ref IntVector2 vector, ref IntVector2 scale, out IntVector2 result)
+        {
+            result = new IntVector2(vector.X * scale.X, vector.Y * scale.Y);
+        }
+
+        #endregion
+
+        #region Divide
+
+        /// <summary>
+        /// Divides a vector by a scalar.
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of the operation.</returns>
+        public static IntVector2 Divide(IntVector2 vector, int scale)
+        {
+            Divide(ref vector, scale, out vector);
+            return vector;
+        }
+
+        /// <summary>
+        /// Divides a vector by a scalar.
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <param name="result">Result of the operation.</param>
+        public static void Divide(ref IntVector2 vector, int scale, out IntVector2 result)
+        {
+            Multiply(ref vector, 1 / scale, out result);
+        }
+
+        /// <summary>
+        /// Divides a vector by the components of a vector (scale).
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of the operation.</returns>
+        public static IntVector2 Divide(IntVector2 vector, IntVector2 scale)
+        {
+            Divide(ref vector, ref scale, out vector);
+            return vector;
+        }
+
+        /// <summary>
+        /// Divide a vector by the components of a vector (scale).
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <param name="result">Result of the operation.</param>
+        public static void Divide(ref IntVector2 vector, ref IntVector2 scale, out IntVector2 result)
+        {
+            result = new IntVector2(vector.X / scale.X, vector.Y / scale.Y);
+        }
+
+        #endregion
+
+        #region ComponentMin
+
+        /// <summary>
+        /// Calculate the component-wise minimum of two vectors
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <returns>The component-wise minimum</returns>
+        public static IntVector2 ComponentMin(IntVector2 a, IntVector2 b)
+        {
+            a.X = a.X < b.X ? a.X : b.X;
+            a.Y = a.Y < b.Y ? a.Y : b.Y;
+            return a;
+        }
+
+        /// <summary>
+        /// Calculate the component-wise minimum of two vectors
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <param name="result">The component-wise minimum</param>
+        public static void ComponentMin(ref IntVector2 a, ref IntVector2 b, out IntVector2 result)
+        {
+            result.X = a.X < b.X ? a.X : b.X;
+            result.Y = a.Y < b.Y ? a.Y : b.Y;
+        }
+
+        #endregion
+
+        #region ComponentMax
+
+        /// <summary>
+        /// Calculate the component-wise maximum of two vectors
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <returns>The component-wise maximum</returns>
+        public static IntVector2 ComponentMax(IntVector2 a, IntVector2 b)
+        {
+            a.X = a.X > b.X ? a.X : b.X;
+            a.Y = a.Y > b.Y ? a.Y : b.Y;
+            return a;
+        }
+
+        /// <summary>
+        /// Calculate the component-wise maximum of two vectors
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <param name="result">The component-wise maximum</param>
+        public static void ComponentMax(ref IntVector2 a, ref IntVector2 b, out IntVector2 result)
+        {
+            result.X = a.X > b.X ? a.X : b.X;
+            result.Y = a.Y > b.Y ? a.Y : b.Y;
+        }
+
+        #endregion
+
+        #region Min
+
+        /// <summary>
+        /// Returns the Vector3 with the minimum magnitude
+        /// </summary>
+        /// <param name="left">Left operand</param>
+        /// <param name="right">Right operand</param>
+        /// <returns>The minimum Vector3</returns>
+        public static IntVector2 Min(IntVector2 left, IntVector2 right)
+        {
+            return left.LengthSquared < right.LengthSquared ? left : right;
+        }
+
+        #endregion
+
+        #region Max
+
+        /// <summary>
+        /// Returns the Vector3 with the minimum magnitude
+        /// </summary>
+        /// <param name="left">Left operand</param>
+        /// <param name="right">Right operand</param>
+        /// <returns>The minimum Vector3</returns>
+        public static IntVector2 Max(IntVector2 left, IntVector2 right)
+        {
+            return left.LengthSquared >= right.LengthSquared ? left : right;
+        }
+
+        #endregion
+
+        #region Clamp
+
+        /// <summary>
+        /// Clamp a vector to the given minimum and maximum vectors
+        /// </summary>
+        /// <param name="vec">Input vector</param>
+        /// <param name="min">Minimum vector</param>
+        /// <param name="max">Maximum vector</param>
+        /// <returns>The clamped vector</returns>
+        public static IntVector2 Clamp(IntVector2 vec, IntVector2 min, IntVector2 max)
+        {
+            vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
+            vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
+            return vec;
+        }
+
+        /// <summary>
+        /// Clamp a vector to the given minimum and maximum vectors
+        /// </summary>
+        /// <param name="vec">Input vector</param>
+        /// <param name="min">Minimum vector</param>
+        /// <param name="max">Maximum vector</param>
+        /// <param name="result">The clamped vector</param>
+        public static void Clamp(ref IntVector2 vec, ref IntVector2 min, ref IntVector2 max, out IntVector2 result)
+        {
+            result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
+            result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
+        }
+
+        #endregion
+
+        #region Normalize
+
+        /// <summary>
+        /// Scale a vector to unit length
+        /// </summary>
+        /// <param name="vec">The input vector</param>
+        /// <returns>The normalized vector</returns>
+        public static IntVector2 Normalize(IntVector2 vec)
+        {
+            vec.X = vec.X / vec.Length;
+            vec.Y = vec.Y / vec.Length;
+            return vec;
+        }
+
+        /// <summary>
+        /// Scale a vector to unit length
+        /// </summary>
+        /// <param name="vec">The input vector</param>
+        /// <param name="result">The normalized vector</param>
+        public static void Normalize(ref IntVector2 vec, out IntVector2 result)
+        {
+            result.X = vec.X / vec.Length;
+            result.Y = vec.Y / vec.Length;
+        }
+
+        #endregion
+
+        #region NormalizeFast
+
+        /// <summary>
+        /// Scale a vector to approximately unit length
+        /// </summary>
+        /// <param name="vec">The input vector</param>
+        /// <returns>The normalized vector</returns>
+        public static IntVector2 NormalizeFast(IntVector2 vec)
+        {
+            int scale = (int) MathHelper.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
+            vec.X *= scale;
+            vec.Y *= scale;
+            return vec;
+        }
+
+        /// <summary>
+        /// Scale a vector to approximately unit length
+        /// </summary>
+        /// <param name="vec">The input vector</param>
+        /// <param name="result">The normalized vector</param>
+        public static void NormalizeFast(ref IntVector2 vec, out IntVector2 result)
+        {
+            int scale = (int) MathHelper.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
+            result.X = vec.X * scale;
+            result.Y = vec.Y * scale;
+        }
+
+        #endregion
+
+        #region Dot
+
+        /// <summary>
+        /// Calculate the dot (scalar) product of two vectors
+        /// </summary>
+        /// <param name="left">First operand</param>
+        /// <param name="right">Second operand</param>
+        /// <returns>The dot product of the two inputs</returns>
+        public static int Dot(IntVector2 left, IntVector2 right)
+        {
+            return left.X * right.X + left.Y * right.Y;
+        }
+
+        /// <summary>
+        /// Calculate the dot (scalar) product of two vectors
+        /// </summary>
+        /// <param name="left">First operand</param>
+        /// <param name="right">Second operand</param>
+        /// <param name="result">The dot product of the two inputs</param>
+        public static void Dot(ref IntVector2 left, ref IntVector2 right, out int result)
+        {
+            result = left.X * right.X + left.Y * right.Y;
+        }
+
+        #endregion
+
+        #region Lerp
+
+        /// <summary>
+        /// Returns a new Vector that is the linear blend of the 2 given Vectors
+        /// </summary>
+        /// <param name="a">First input vector</param>
+        /// <param name="b">Second input vector</param>
+        /// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
+        /// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
+        public static IntVector2 Lerp(IntVector2 a, IntVector2 b, int blend)
+        {
+            a.X = blend * (b.X - a.X) + a.X;
+            a.Y = blend * (b.Y - a.Y) + a.Y;
+            return a;
+        }
+
+        /// <summary>
+        /// Returns a new Vector that is the linear blend of the 2 given Vectors
+        /// </summary>
+        /// <param name="a">First input vector</param>
+        /// <param name="b">Second input vector</param>
+        /// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
+        /// <param name="result">a when blend=0, b when blend=1, and a linear combination otherwise</param>
+        public static void Lerp(ref IntVector2 a, ref IntVector2 b, int blend, out IntVector2 result)
+        {
+            result.X = blend * (b.X - a.X) + a.X;
+            result.Y = blend * (b.Y - a.Y) + a.Y;
+        }
+
+        #endregion
+
+        #region Barycentric
+
+        /// <summary>
+        /// Interpolate 3 Vectors using Barycentric coordinates
+        /// </summary>
+        /// <param name="a">First input Vector</param>
+        /// <param name="b">Second input Vector</param>
+        /// <param name="c">Third input Vector</param>
+        /// <param name="u">First Barycentric Coordinate</param>
+        /// <param name="v">Second Barycentric Coordinate</param>
+        /// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
+        public static IntVector2 BaryCentric(IntVector2 a, IntVector2 b, IntVector2 c, int u, int v)
+        {
+            return a + u * (b - a) + v * (c - a);
+        }
+
+        /// <summary>Interpolate 3 Vectors using Barycentric coordinates</summary>
+        /// <param name="a">First input Vector.</param>
+        /// <param name="b">Second input Vector.</param>
+        /// <param name="c">Third input Vector.</param>
+        /// <param name="u">First Barycentric Coordinate.</param>
+        /// <param name="v">Second Barycentric Coordinate.</param>
+        /// <param name="result">Output Vector. a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</param>
+        public static void BaryCentric(ref IntVector2 a, ref IntVector2 b, ref IntVector2 c, int u, int v, out IntVector2 result)
+        {
+            result = a; // copy
+
+            IntVector2 temp = b; // copy
+            Subtract(ref temp, ref a, out temp);
+            Multiply(ref temp, u, out temp);
+            Add(ref result, ref temp, out result);
+
+            temp = c; // copy
+            Subtract(ref temp, ref a, out temp);
+            Multiply(ref temp, v, out temp);
+            Add(ref result, ref temp, out result);
+        }
+
+        #endregion
+
+        #endregion
+
+        #region Operators
+
+        /// <summary>
+        /// Adds the specified instances.
+        /// </summary>
+        /// <param name="left">Left operand.</param>
+        /// <param name="right">Right operand.</param>
+        /// <returns>Result of addition.</returns>
+        public static IntVector2 operator +(IntVector2 left, IntVector2 right)
+        {
+            left.X += right.X;
+            left.Y += right.Y;
+            return left;
+        }
+
+        /// <summary>
+        /// Subtracts the specified instances.
+        /// </summary>
+        /// <param name="left">Left operand.</param>
+        /// <param name="right">Right operand.</param>
+        /// <returns>Result of subtraction.</returns>
+        public static IntVector2 operator -(IntVector2 left, IntVector2 right)
+        {
+            left.X -= right.X;
+            left.Y -= right.Y;
+            return left;
+        }
+
+        /// <summary>
+        /// Negates the specified instance.
+        /// </summary>
+        /// <param name="vec">Operand.</param>
+        /// <returns>Result of negation.</returns>
+        public static IntVector2 operator -(IntVector2 vec)
+        {
+            vec.X = -vec.X;
+            vec.Y = -vec.Y;
+            return vec;
+        }
+
+        /// <summary>
+        /// Multiplies the specified instance by a scalar.
+        /// </summary>
+        /// <param name="vec">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of multiplication.</returns>
+        public static IntVector2 operator *(IntVector2 vec, int scale)
+        {
+            vec.X *= scale;
+            vec.Y *= scale;
+            return vec;
+        }
+
+        /// <summary>
+        /// Multiplies the specified instance by a scalar.
+        /// </summary>
+        /// <param name="scale">Left operand.</param>
+        /// <param name="vec">Right operand.</param>
+        /// <returns>Result of multiplication.</returns>
+        public static IntVector2 operator *(int scale, IntVector2 vec)
+        {
+            vec.X *= scale;
+            vec.Y *= scale;
+            return vec;
+        }
+
+        /// <summary>
+        /// Divides the specified instance by a scalar.
+        /// </summary>
+        /// <param name="vec">Left operand</param>
+        /// <param name="scale">Right operand</param>
+        /// <returns>Result of the division.</returns>
+        public static IntVector2 operator /(IntVector2 vec, int scale)
+        {
+            vec.X = vec.X / scale;
+            vec.Y = vec.Y / scale;
+            return vec;
+        }
+
+        /// <summary>
+        /// Compares the specified instances for equality.
+        /// </summary>
+        /// <param name="left">Left operand.</param>
+        /// <param name="right">Right operand.</param>
+        /// <returns>True if both instances are equal; false otherwise.</returns>
+        public static bool operator ==(IntVector2 left, IntVector2 right)
+        {
+            return left.Equals(right);
+        }
+
+        /// <summary>
+        /// Compares the specified instances for inequality.
+        /// </summary>
+        /// <param name="left">Left operand.</param>
+        /// <param name="right">Right operand.</param>
+        /// <returns>True if both instances are not equal; false otherwise.</returns>
+        public static bool operator !=(IntVector2 left, IntVector2 right)
+        {
+            return !left.Equals(right);
+        }
+
+        #endregion
+
+        #region Overrides
+
+        #region public override string ToString()
+
+        /// <summary>
+        /// Returns a System.String that represents the current IntVector2.
+        /// </summary>
+        /// <returns></returns>
+        public override string ToString()
+        {
+            return String.Format("({0}, {1})", X, Y);
+        }
+
+        #endregion
+
+        #region public override int GetHashCode()
+
+        /// <summary>
+        /// Returns the hashcode for this instance.
+        /// </summary>
+        /// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
+        public override int GetHashCode()
+        {
+            return X.GetHashCode() ^ Y.GetHashCode();
+        }
+
+        #endregion
+
+        #region public override bool Equals(object obj)
+
+        /// <summary>
+        /// Indicates whether this instance and a specified object are equal.
+        /// </summary>
+        /// <param name="obj">The object to compare to.</param>
+        /// <returns>True if the instances are equal; false otherwise.</returns>
+        public override bool Equals(object obj)
+        {
+            if (!(obj is IntVector2))
+                return false;
+
+            return this.Equals((IntVector2)obj);
+        }
+
+        #endregion
+
+        #endregion
+
+        #endregion
+
+        #region IEquatable<IntVector2> Members
+
+        /// <summary>Indicates whether the current vector is equal to another vector.</summary>
+        /// <param name="other">A vector to compare with this vector.</param>
+        /// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
+        public bool Equals(IntVector2 other)
+        {
+            return
+                X == other.X &&
+                Y == other.Y;
+        }
+
+        #endregion
+
+        public bool IsEmpty => X == 0 && Y == 0;
+    }
 }

+ 9 - 9
Script/AtomicNET/AtomicNET/Math/MathHelper.cs

@@ -198,15 +198,15 @@ namespace AtomicEngine
             return InverseSqrtFast((float)x);
             // TODO: The following code is wrong. Fix it, to improve precision.
 #if false
-			unsafe
-			{
-				double xhalf = 0.5f * x;
-				int i = *(int*)&x;              // Read bits as integer.
-				i = 0x5f375a86 - (i >> 1);      // Make an initial guess for Newton-Raphson approximation
-				x = *(float*)&i;                // Convert bits back to float
-				x = x * (1.5f - xhalf * x * x); // Perform left single Newton-Raphson step.
-				return x;
-			}
+            unsafe
+            {
+                double xhalf = 0.5f * x;
+                int i = *(int*)&x;              // Read bits as integer.
+                i = 0x5f375a86 - (i >> 1);      // Make an initial guess for Newton-Raphson approximation
+                x = *(float*)&i;                // Convert bits back to float
+                x = x * (1.5f - xhalf * x * x); // Perform left single Newton-Raphson step.
+                return x;
+            }
 #endif
         }
 

+ 766 - 766
Script/AtomicNET/AtomicNET/Math/Matrix3.cs

@@ -27,770 +27,770 @@ using System.Runtime.InteropServices;
 
 namespace AtomicEngine
 {
-	// Todo: Remove this warning when the code goes public.
-	#pragma warning disable 3019
-	[StructLayout(LayoutKind.Sequential)]
-	public struct Matrix3 : IEquatable<Matrix3>
-	{
-		#region Fields & Access
-
-		/// <summary>Row 0, Column 0</summary>
-		public float R0C0;
-
-		/// <summary>Row 0, Column 1</summary>
-		public float R0C1;
-
-		/// <summary>Row 0, Column 2</summary>
-		public float R0C2;
-
-		/// <summary>Row 1, Column 0</summary>
-		public float R1C0;
-
-		/// <summary>Row 1, Column 1</summary>
-		public float R1C1;
-
-		/// <summary>Row 1, Column 2</summary>
-		public float R1C2;
-
-		/// <summary>Row 2, Column 0</summary>
-		public float R2C0;
-
-		/// <summary>Row 2, Column 1</summary>
-		public float R2C1;
-
-		/// <summary>Row 2, Column 2</summary>
-		public float R2C2;
-
-		/// <summary>Gets the component at the given row and column in the matrix.</summary>
-		/// <param name="row">The row of the matrix.</param>
-		/// <param name="column">The column of the matrix.</param>
-		/// <returns>The component at the given row and column in the matrix.</returns>
-		public float this[int row, int column]
-		{
-			get
-			{
-				switch( row )
-				{
-					case 0:
-						switch (column)
-						{
-							case 0: return R0C0;
-							case 1: return R0C1;
-							case 2: return R0C2;
-						}
-						break;
-
-					case 1:
-						switch (column)
-						{
-							case 0: return R1C0;
-							case 1: return R1C1;
-							case 2: return R1C2;
-						}
-						break;
-
-					case 2:
-						switch (column)
-						{
-							case 0: return R2C0;
-							case 1: return R2C1;
-							case 2: return R2C2;
-						}
-						break;
-				}
-
-				throw new IndexOutOfRangeException();
-			}
-			set
-			{
-				switch( row )
-				{
-					case 0:
-						switch (column)
-						{
-							case 0: R0C0 = value; return;
-							case 1: R0C1 = value; return;
-							case 2: R0C2 = value; return;
-						}
-						break;
-
-					case 1:
-						switch (column)
-						{
-							case 0: R1C0 = value; return;
-							case 1: R1C1 = value; return;
-							case 2: R1C2 = value; return;
-						}
-						break;
-
-					case 2:
-						switch (column)
-						{
-							case 0: R2C0 = value; return;
-							case 1: R2C1 = value; return;
-							case 2: R2C2 = value; return;
-						}
-						break;
-				}
-
-				throw new IndexOutOfRangeException();
-			}
-		}
-
-		/// <summary>Gets the component at the index into the matrix.</summary>
-		/// <param name="index">The index into the components of the matrix.</param>
-		/// <returns>The component at the given index into the matrix.</returns>
-		public float this[int index]
-		{
-			get
-			{
-				switch (index)
-				{
-					case 0: return R0C0;
-					case 1: return R0C1;
-					case 2: return R0C2;
-					case 3: return R1C0;
-					case 4: return R1C1;
-					case 5: return R1C2;
-					case 6: return R2C0;
-					case 7: return R2C1;
-					case 8: return R2C2;
-					default: throw new IndexOutOfRangeException();
-				}
-			}
-			set
-			{
-				switch (index)
-				{
-					case 0: R0C0 = value; return;
-					case 1: R0C1 = value; return;
-					case 2: R0C2 = value; return;
-					case 3: R1C0 = value; return;
-					case 4: R1C1 = value; return;
-					case 5: R1C2 = value; return;
-					case 6: R2C0 = value; return;
-					case 7: R2C1 = value; return;
-					case 8: R2C2 = value; return;
-					default: throw new IndexOutOfRangeException();
-				}
-			}
-		}
-
-		/// <summary>Converts the matrix into an IntPtr.</summary>
-		/// <param name="matrix">The matrix to convert.</param>
-		/// <returns>An IntPtr for the matrix.</returns>
-		public static explicit operator IntPtr(Matrix3 matrix)
-		{
-			unsafe
-			{
-				return (IntPtr)(&matrix.R0C0);
-			}
-		}
-
-		/// <summary>Converts the matrix into left float*.</summary>
-		/// <param name="matrix">The matrix to convert.</param>
-		/// <returns>A float* for the matrix.</returns>
-		[CLSCompliant(false)]
-		unsafe public static explicit operator float*(Matrix3 matrix)
-		{
-			return &matrix.R0C0;
-		}
-
-		/// <summary>Converts the matrix into an array of floats.</summary>
-		/// <param name="matrix">The matrix to convert.</param>
-		/// <returns>An array of floats for the matrix.</returns>
-		public static explicit operator float[](Matrix3 matrix)
-		{
-			return new float[9]
-			{
-				matrix.R0C0,
-				matrix.R0C1,
-				matrix.R0C2,
-				matrix.R1C0,
-				matrix.R1C1,
-				matrix.R1C2,
-				matrix.R2C0,
-				matrix.R2C1,
-				matrix.R2C2
-			};
-		}
-
-		#endregion
-
-		#region Constructors
-
-		/// <summary>Constructs left matrix with the same components as the given matrix.</summary>
-		/// <param name="vector">The matrix whose components to copy.</param>
-		public Matrix3(ref Matrix3 matrix)
-		{
-			this.R0C0 = matrix.R0C0;
-			this.R0C1 = matrix.R0C1;
-			this.R0C2 = matrix.R0C2;
-			this.R1C0 = matrix.R1C0;
-			this.R1C1 = matrix.R1C1;
-			this.R1C2 = matrix.R1C2;
-			this.R2C0 = matrix.R2C0;
-			this.R2C1 = matrix.R2C1;
-			this.R2C2 = matrix.R2C2;
-		}
-
-		/// <summary>Constructs left matrix with the given values.</summary>
-		/// <param name="r0c0">The value for row 0 column 0.</param>
-		/// <param name="r0c1">The value for row 0 column 1.</param>
-		/// <param name="r0c2">The value for row 0 column 2.</param>
-		/// <param name="r1c0">The value for row 1 column 0.</param>
-		/// <param name="r1c1">The value for row 1 column 1.</param>
-		/// <param name="r1c2">The value for row 1 column 2.</param>
-		/// <param name="r2c0">The value for row 2 column 0.</param>
-		/// <param name="r2c1">The value for row 2 column 1.</param>
-		/// <param name="r2c2">The value for row 2 column 2.</param>
-		public Matrix3
-		(
-			float r0c0,
-			float r0c1,
-			float r0c2,
-			float r1c0,
-			float r1c1,
-			float r1c2,
-			float r2c0,
-			float r2c1,
-			float r2c2
-		)
-		{
-			this.R0C0 = r0c0;
-			this.R0C1 = r0c1;
-			this.R0C2 = r0c2;
-			this.R1C0 = r1c0;
-			this.R1C1 = r1c1;
-			this.R1C2 = r1c2;
-			this.R2C0 = r2c0;
-			this.R2C1 = r2c1;
-			this.R2C2 = r2c2;
-		}
-
-		/// <summary>Constructs left matrix from the given array of float-precision floating-point numbers.</summary>
-		/// <param name="floatArray">The array of floats for the components of the matrix.</param>
-		public Matrix3(float[] floatArray)
-		{
-			if (floatArray == null || floatArray.GetLength(0) < 9) throw new InvalidOperationException();
-
-			this.R0C0 = floatArray[0];
-			this.R0C1 = floatArray[1];
-			this.R0C2 = floatArray[2];
-			this.R1C0 = floatArray[3];
-			this.R1C1 = floatArray[4];
-			this.R1C2 = floatArray[5];
-			this.R2C0 = floatArray[6];
-			this.R2C1 = floatArray[7];
-			this.R2C2 = floatArray[8];
-		}
-
-		#endregion
-
-		#region Equality
-
-		/// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
-		/// <param name="matrix">The OpenTK.Matrix3 structure to compare with.</param>
-		/// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
-		[CLSCompliant(false)]
-		public bool Equals(Matrix3 matrix)
-		{
-			return
-				R0C0 == matrix.R0C0 &&
-				R0C1 == matrix.R0C1 &&
-				R0C2 == matrix.R0C2 &&
-				R1C0 == matrix.R1C0 &&
-				R1C1 == matrix.R1C1 &&
-				R1C2 == matrix.R1C2 &&
-				R2C0 == matrix.R2C0 &&
-				R2C1 == matrix.R2C1 &&
-				R2C2 == matrix.R2C2;
-		}
-
-		/// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
-		/// <param name="matrix">The OpenTK.Matrix3 structure to compare to.</param>
-		/// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
-		public bool Equals(ref Matrix3 matrix)
-		{
-			return
-				R0C0 == matrix.R0C0 &&
-				R0C1 == matrix.R0C1 &&
-				R0C2 == matrix.R0C2 &&
-				R1C0 == matrix.R1C0 &&
-				R1C1 == matrix.R1C1 &&
-				R1C2 == matrix.R1C2 &&
-				R2C0 == matrix.R2C0 &&
-				R2C1 == matrix.R2C1 &&
-				R2C2 == matrix.R2C2;
-		}
-
-		/// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
-		/// <param name="left">The left-hand operand.</param>
-		/// <param name="right">The right-hand operand.</param>
-		/// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
-		public static bool Equals(ref Matrix3 left, ref Matrix3 right)
-		{
-			return
-				left.R0C0 == right.R0C0 &&
-				left.R0C1 == right.R0C1 &&
-				left.R0C2 == right.R0C2 &&
-				left.R1C0 == right.R1C0 &&
-				left.R1C1 == right.R1C1 &&
-				left.R1C2 == right.R1C2 &&
-				left.R2C0 == right.R2C0 &&
-				left.R2C1 == right.R2C1 &&
-				left.R2C2 == right.R2C2;
-		}
-
-		/// <summary>Indicates whether the current matrix is approximately equal to another matrix.</summary>
-		/// <param name="matrix">The OpenTK.Matrix3 structure to compare with.</param>
-		/// <param name="tolerance">The limit below which the matrices are considered equal.</param>
-		/// <returns>true if the current matrix is approximately equal to the matrix parameter; otherwise, false.</returns>
-		public bool EqualsApprox(ref Matrix3 matrix, float tolerance)
-		{
-			return
-				System.Math.Abs(R0C0 - matrix.R0C0) <= tolerance &&
-				System.Math.Abs(R0C1 - matrix.R0C1) <= tolerance &&
-				System.Math.Abs(R0C2 - matrix.R0C2) <= tolerance &&
-				System.Math.Abs(R1C0 - matrix.R1C0) <= tolerance &&
-				System.Math.Abs(R1C1 - matrix.R1C1) <= tolerance &&
-				System.Math.Abs(R1C2 - matrix.R1C2) <= tolerance &&
-				System.Math.Abs(R2C0 - matrix.R2C0) <= tolerance &&
-				System.Math.Abs(R2C1 - matrix.R2C1) <= tolerance &&
-				System.Math.Abs(R2C2 - matrix.R2C2) <= tolerance;
-		}
-
-		/// <summary>Indicates whether the current matrix is approximately equal to another matrix.</summary>
-		/// <param name="left">The left-hand operand.</param>
-		/// <param name="right">The right-hand operand.</param>
-		/// <param name="tolerance">The limit below which the matrices are considered equal.</param>
-		/// <returns>true if the current matrix is approximately equal to the matrix parameter; otherwise, false.</returns>
-		public static bool EqualsApprox(ref Matrix3 left, ref Matrix3 right, float tolerance)
-		{
-			return
-				System.Math.Abs(left.R0C0 - right.R0C0) <= tolerance &&
-				System.Math.Abs(left.R0C1 - right.R0C1) <= tolerance &&
-				System.Math.Abs(left.R0C2 - right.R0C2) <= tolerance &&
-				System.Math.Abs(left.R1C0 - right.R1C0) <= tolerance &&
-				System.Math.Abs(left.R1C1 - right.R1C1) <= tolerance &&
-				System.Math.Abs(left.R1C2 - right.R1C2) <= tolerance &&
-				System.Math.Abs(left.R2C0 - right.R2C0) <= tolerance &&
-				System.Math.Abs(left.R2C1 - right.R2C1) <= tolerance &&
-				System.Math.Abs(left.R2C2 - right.R2C2) <= tolerance;
-		}
-
-		#endregion
-
-		#region Arithmetic Operators
-
-
-		/// <summary>Add left matrix to this matrix.</summary>
-		/// <param name="matrix">The matrix to add.</param>
-		public void Add(ref Matrix3 matrix)
-		{
-			R0C0 = R0C0 + matrix.R0C0;
-			R0C1 = R0C1 + matrix.R0C1;
-			R0C2 = R0C2 + matrix.R0C2;
-			R1C0 = R1C0 + matrix.R1C0;
-			R1C1 = R1C1 + matrix.R1C1;
-			R1C2 = R1C2 + matrix.R1C2;
-			R2C0 = R2C0 + matrix.R2C0;
-			R2C1 = R2C1 + matrix.R2C1;
-			R2C2 = R2C2 + matrix.R2C2;
-		}
-
-		/// <summary>Add left matrix to this matrix.</summary>
-		/// <param name="matrix">The matrix to add.</param>
-		/// <param name="result">The resulting matrix of the addition.</param>
-		public void Add(ref Matrix3 matrix, out Matrix3 result)
-		{
-			result.R0C0 = R0C0 + matrix.R0C0;
-			result.R0C1 = R0C1 + matrix.R0C1;
-			result.R0C2 = R0C2 + matrix.R0C2;
-			result.R1C0 = R1C0 + matrix.R1C0;
-			result.R1C1 = R1C1 + matrix.R1C1;
-			result.R1C2 = R1C2 + matrix.R1C2;
-			result.R2C0 = R2C0 + matrix.R2C0;
-			result.R2C1 = R2C1 + matrix.R2C1;
-			result.R2C2 = R2C2 + matrix.R2C2;
-		}
-
-		/// <summary>Add left matrix to left matrix.</summary>
-		/// <param name="matrix">The matrix on the matrix side of the equation.</param>
-		/// <param name="right">The matrix on the right side of the equation</param>
-		/// <param name="result">The resulting matrix of the addition.</param>
-		public static void Add(ref Matrix3 left, ref Matrix3 right, out Matrix3 result)
-		{
-			result.R0C0 = left.R0C0 + right.R0C0;
-			result.R0C1 = left.R0C1 + right.R0C1;
-			result.R0C2 = left.R0C2 + right.R0C2;
-			result.R1C0 = left.R1C0 + right.R1C0;
-			result.R1C1 = left.R1C1 + right.R1C1;
-			result.R1C2 = left.R1C2 + right.R1C2;
-			result.R2C0 = left.R2C0 + right.R2C0;
-			result.R2C1 = left.R2C1 + right.R2C1;
-			result.R2C2 = left.R2C2 + right.R2C2;
-		}
-
-
-		/// <summary>Subtract left matrix from this matrix.</summary>
-		/// <param name="matrix">The matrix to subtract.</param>
-		public void Subtract(ref Matrix3 matrix)
-		{
-			R0C0 = R0C0 + matrix.R0C0;
-			R0C1 = R0C1 + matrix.R0C1;
-			R0C2 = R0C2 + matrix.R0C2;
-			R1C0 = R1C0 + matrix.R1C0;
-			R1C1 = R1C1 + matrix.R1C1;
-			R1C2 = R1C2 + matrix.R1C2;
-			R2C0 = R2C0 + matrix.R2C0;
-			R2C1 = R2C1 + matrix.R2C1;
-			R2C2 = R2C2 + matrix.R2C2;
-		}
-
-		/// <summary>Subtract left matrix from this matrix.</summary>
-		/// <param name="matrix">The matrix to subtract.</param>
-		/// <param name="result">The resulting matrix of the subtraction.</param>
-		public void Subtract(ref Matrix3 matrix, out Matrix3 result)
-		{
-			result.R0C0 = R0C0 + matrix.R0C0;
-			result.R0C1 = R0C1 + matrix.R0C1;
-			result.R0C2 = R0C2 + matrix.R0C2;
-			result.R1C0 = R1C0 + matrix.R1C0;
-			result.R1C1 = R1C1 + matrix.R1C1;
-			result.R1C2 = R1C2 + matrix.R1C2;
-			result.R2C0 = R2C0 + matrix.R2C0;
-			result.R2C1 = R2C1 + matrix.R2C1;
-			result.R2C2 = R2C2 + matrix.R2C2;
-		}
-
-		/// <summary>Subtract left matrix from left matrix.</summary>
-		/// <param name="matrix">The matrix on the matrix side of the equation.</param>
-		/// <param name="right">The matrix on the right side of the equation</param>
-		/// <param name="result">The resulting matrix of the subtraction.</param>
-		public static void Subtract(ref Matrix3 left, ref Matrix3 right, out Matrix3 result)
-		{
-			result.R0C0 = left.R0C0 + right.R0C0;
-			result.R0C1 = left.R0C1 + right.R0C1;
-			result.R0C2 = left.R0C2 + right.R0C2;
-			result.R1C0 = left.R1C0 + right.R1C0;
-			result.R1C1 = left.R1C1 + right.R1C1;
-			result.R1C2 = left.R1C2 + right.R1C2;
-			result.R2C0 = left.R2C0 + right.R2C0;
-			result.R2C1 = left.R2C1 + right.R2C1;
-			result.R2C2 = left.R2C2 + right.R2C2;
-		}
-
-
-		/// <summary>Multiply left martix times this matrix.</summary>
-		/// <param name="matrix">The matrix to multiply.</param>
-		public void Multiply(ref Matrix3 matrix)
-		{
-			float r0c0 = matrix.R0C0 * R0C0 + matrix.R0C1 * R1C0 + matrix.R0C2 * R2C0;
-			float r0c1 = matrix.R0C0 * R0C1 + matrix.R0C1 * R1C1 + matrix.R0C2 * R2C1;
-			float r0c2 = matrix.R0C0 * R0C2 + matrix.R0C1 * R1C2 + matrix.R0C2 * R2C2;
-
-			float r1c0 = matrix.R1C0 * R0C0 + matrix.R1C1 * R1C0 + matrix.R1C2 * R2C0;
-			float r1c1 = matrix.R1C0 * R0C1 + matrix.R1C1 * R1C1 + matrix.R1C2 * R2C1;
-			float r1c2 = matrix.R1C0 * R0C2 + matrix.R1C1 * R1C2 + matrix.R1C2 * R2C2;
-
-			R2C0 = matrix.R2C0 * R0C0 + matrix.R2C1 * R1C0 + matrix.R2C2 * R2C0;
-			R2C1 = matrix.R2C0 * R0C1 + matrix.R2C1 * R1C1 + matrix.R2C2 * R2C1;
-			R2C2 = matrix.R2C0 * R0C2 + matrix.R2C1 * R1C2 + matrix.R2C2 * R2C2;
-
-
-			R0C0 = r0c0;
-			R0C1 = r0c1;
-			R0C2 = r0c2;
-
-			R1C0 = r1c0;
-			R1C1 = r1c1;
-			R1C2 = r1c2;
-		}
-
-		/// <summary>Multiply matrix times this matrix.</summary>
-		/// <param name="matrix">The matrix to multiply.</param>
-		/// <param name="result">The resulting matrix of the multiplication.</param>
-		public void Multiply(ref Matrix3 matrix, out Matrix3 result)
-		{
-			result.R0C0 = matrix.R0C0 * R0C0 + matrix.R0C1 * R1C0 + matrix.R0C2 * R2C0;
-			result.R0C1 = matrix.R0C0 * R0C1 + matrix.R0C1 * R1C1 + matrix.R0C2 * R2C1;
-			result.R0C2 = matrix.R0C0 * R0C2 + matrix.R0C1 * R1C2 + matrix.R0C2 * R2C2;
-			result.R1C0 = matrix.R1C0 * R0C0 + matrix.R1C1 * R1C0 + matrix.R1C2 * R2C0;
-			result.R1C1 = matrix.R1C0 * R0C1 + matrix.R1C1 * R1C1 + matrix.R1C2 * R2C1;
-			result.R1C2 = matrix.R1C0 * R0C2 + matrix.R1C1 * R1C2 + matrix.R1C2 * R2C2;
-			result.R2C0 = matrix.R2C0 * R0C0 + matrix.R2C1 * R1C0 + matrix.R2C2 * R2C0;
-			result.R2C1 = matrix.R2C0 * R0C1 + matrix.R2C1 * R1C1 + matrix.R2C2 * R2C1;
-			result.R2C2 = matrix.R2C0 * R0C2 + matrix.R2C1 * R1C2 + matrix.R2C2 * R2C2;
-		}
-
-		/// <summary>Multiply left matrix times left matrix.</summary>
-		/// <param name="matrix">The matrix on the matrix side of the equation.</param>
-		/// <param name="right">The matrix on the right side of the equation</param>
-		/// <param name="result">The resulting matrix of the multiplication.</param>
-		public static void Multiply(ref Matrix3 left, ref Matrix3 right, out Matrix3 result)
-		{
-			result.R0C0 = right.R0C0 * left.R0C0 + right.R0C1 * left.R1C0 + right.R0C2 * left.R2C0;
-			result.R0C1 = right.R0C0 * left.R0C1 + right.R0C1 * left.R1C1 + right.R0C2 * left.R2C1;
-			result.R0C2 = right.R0C0 * left.R0C2 + right.R0C1 * left.R1C2 + right.R0C2 * left.R2C2;
-			result.R1C0 = right.R1C0 * left.R0C0 + right.R1C1 * left.R1C0 + right.R1C2 * left.R2C0;
-			result.R1C1 = right.R1C0 * left.R0C1 + right.R1C1 * left.R1C1 + right.R1C2 * left.R2C1;
-			result.R1C2 = right.R1C0 * left.R0C2 + right.R1C1 * left.R1C2 + right.R1C2 * left.R2C2;
-			result.R2C0 = right.R2C0 * left.R0C0 + right.R2C1 * left.R1C0 + right.R2C2 * left.R2C0;
-			result.R2C1 = right.R2C0 * left.R0C1 + right.R2C1 * left.R1C1 + right.R2C2 * left.R2C1;
-			result.R2C2 = right.R2C0 * left.R0C2 + right.R2C1 * left.R1C2 + right.R2C2 * left.R2C2;
-		}
-
-
-		/// <summary>Multiply matrix times this matrix.</summary>
-		/// <param name="matrix">The matrix to multiply.</param>
-		public void Multiply(float scalar)
-		{
-			R0C0 = scalar * R0C0;
-			R0C1 = scalar * R0C1;
-			R0C2 = scalar * R0C2;
-			R1C0 = scalar * R1C0;
-			R1C1 = scalar * R1C1;
-			R1C2 = scalar * R1C2;
-			R2C0 = scalar * R2C0;
-			R2C1 = scalar * R2C1;
-			R2C2 = scalar * R2C2;
-		}
-
-		/// <summary>Multiply matrix times this matrix.</summary>
-		/// <param name="matrix">The matrix to multiply.</param>
-		/// <param name="result">The resulting matrix of the multiplication.</param>
-		public void Multiply(float scalar, out Matrix3 result)
-		{
-			result.R0C0 = scalar * R0C0;
-			result.R0C1 = scalar * R0C1;
-			result.R0C2 = scalar * R0C2;
-			result.R1C0 = scalar * R1C0;
-			result.R1C1 = scalar * R1C1;
-			result.R1C2 = scalar * R1C2;
-			result.R2C0 = scalar * R2C0;
-			result.R2C1 = scalar * R2C1;
-			result.R2C2 = scalar * R2C2;
-		}
-
-		/// <summary>Multiply left matrix times left matrix.</summary>
-		/// <param name="matrix">The matrix on the matrix side of the equation.</param>
-		/// <param name="right">The matrix on the right side of the equation</param>
-		/// <param name="result">The resulting matrix of the multiplication.</param>
-		public static void Multiply(ref Matrix3 matrix, float scalar, out Matrix3 result)
-		{
-			result.R0C0 = scalar * matrix.R0C0;
-			result.R0C1 = scalar * matrix.R0C1;
-			result.R0C2 = scalar * matrix.R0C2;
-			result.R1C0 = scalar * matrix.R1C0;
-			result.R1C1 = scalar * matrix.R1C1;
-			result.R1C2 = scalar * matrix.R1C2;
-			result.R2C0 = scalar * matrix.R2C0;
-			result.R2C1 = scalar * matrix.R2C1;
-			result.R2C2 = scalar * matrix.R2C2;
-		}
-
-
-		#endregion
-
-		#region Functions
-
-		public float Determinant
-		{
-			get
-			{
-				return R0C0 * R1C1 * R2C2 - R0C0 * R1C2 * R2C1 - R0C1 * R1C0 * R2C2 + R0C2 * R1C0 * R2C1 + R0C1 * R1C2 * R2C0 - R0C2 * R1C1 * R2C0;
-			}
-		}
-
-		public void Transpose()
-		{
-			MathHelper.Swap(ref R0C1, ref R1C0);
-			MathHelper.Swap(ref R0C2, ref R2C0);
-			MathHelper.Swap(ref R1C2, ref R2C1);
-		}
-		public void Transpose(out Matrix3 result)
-		{
-			result.R0C0 = R0C0;
-			result.R0C1 = R1C0;
-			result.R0C2 = R2C0;
-			result.R1C0 = R0C1;
-			result.R1C1 = R1C1;
-			result.R1C2 = R2C1;
-			result.R2C0 = R0C2;
-			result.R2C1 = R1C2;
-			result.R2C2 = R2C2;
-		}
-		public static void Transpose(ref Matrix3 matrix, out Matrix3 result)
-		{
-			result.R0C0 = matrix.R0C0;
-			result.R0C1 = matrix.R1C0;
-			result.R0C2 = matrix.R2C0;
-			result.R1C0 = matrix.R0C1;
-			result.R1C1 = matrix.R1C1;
-			result.R1C2 = matrix.R2C1;
-			result.R2C0 = matrix.R0C2;
-			result.R2C1 = matrix.R1C2;
-			result.R2C2 = matrix.R2C2;
-		}
-
-		#endregion
-
-		#region Transformation Functions
-
-		public void Transform(ref Vector3 vector)
-		{
-			float x = R0C0 * vector.X + R0C1 * vector.Y + R0C2 * vector.Z;
-			float y = R1C0 * vector.X + R1C1 * vector.Y + R1C2 * vector.Z;
-			vector.Z = R2C0 * vector.X + R2C1 * vector.Y + R2C2 * vector.Z;
-			vector.X = x;
-			vector.Y = y;
-		}
-		public static void Transform(ref Matrix3 matrix, ref Vector3 vector)
-		{
-			float x = matrix.R0C0 * vector.X + matrix.R0C1 * vector.Y + matrix.R0C2 * vector.Z;
-			float y = matrix.R1C0 * vector.X + matrix.R1C1 * vector.Y + matrix.R1C2 * vector.Z;
-			vector.Z = matrix.R2C0 * vector.X + matrix.R2C1 * vector.Y + matrix.R2C2 * vector.Z;
-			vector.X = x;
-			vector.Y = y;
-		}
-		public void Transform(ref Vector3 vector, out Vector3 result)
-		{
-			result.X = R0C0 * vector.X + R0C1 * vector.Y + R0C2 * vector.Z;
-			result.Y = R1C0 * vector.X + R1C1 * vector.Y + R1C2 * vector.Z;
-			result.Z = R2C0 * vector.X + R2C1 * vector.Y + R2C2 * vector.Z;
-		}
-		public static void Transform(ref Matrix3 matrix, ref Vector3 vector, out Vector3 result)
-		{
-			result.X = matrix.R0C0 * vector.X + matrix.R0C1 * vector.Y + matrix.R0C2 * vector.Z;
-			result.Y = matrix.R1C0 * vector.X + matrix.R1C1 * vector.Y + matrix.R1C2 * vector.Z;
-			result.Z = matrix.R2C0 * vector.X + matrix.R2C1 * vector.Y + matrix.R2C2 * vector.Z;
-		}
-
-		public void Rotate(float angle)
-		{
-		float angleRadians = MathHelper.DegreesToRadians (angle);
-			float sin = (float)System.Math.Sin(angleRadians);
-			float cos = (float)System.Math.Cos(angleRadians);
-
-			float r0c0 = cos * R0C0 + sin * R1C0;
-			float r0c1 = cos * R0C1 + sin * R1C1;
-			float r0c2 = cos * R0C2 + sin * R1C2;
-
-			R1C0 = cos * R1C0 - sin * R0C0;
-			R1C1 = cos * R1C1 - sin * R0C1;
-			R1C2 = cos * R1C2 - sin * R0C2;
-
-			R0C0 = r0c0;
-			R0C1 = r0c1;
-			R0C2 = r0c2;
-		}
-		public void Rotate(float angle, out Matrix3 result)
-		{
-		float angleRadians = MathHelper.DegreesToRadians (angle);
-			float sin = (float)System.Math.Sin(angleRadians);
-			float cos = (float)System.Math.Cos(angleRadians);
-
-			result.R0C0 = cos * R0C0 + sin * R1C0;
-			result.R0C1 = cos * R0C1 + sin * R1C1;
-			result.R0C2 = cos * R0C2 + sin * R1C2;
-			result.R1C0 = cos * R1C0 - sin * R0C0;
-			result.R1C1 = cos * R1C1 - sin * R0C1;
-			result.R1C2 = cos * R1C2 - sin * R0C2;
-			result.R2C0 = R2C0;
-			result.R2C1 = R2C1;
-			result.R2C2 = R2C2;
-		}
-		public static void Rotate(ref Matrix3 matrix, float angle, out Matrix3 result)
-		{
-		float angleRadians = MathHelper.DegreesToRadians (angle);
-			float sin = (float)System.Math.Sin(angleRadians);
-			float cos = (float)System.Math.Cos(angleRadians);
-
-			result.R0C0 = cos * matrix.R0C0 + sin * matrix.R1C0;
-			result.R0C1 = cos * matrix.R0C1 + sin * matrix.R1C1;
-			result.R0C2 = cos * matrix.R0C2 + sin * matrix.R1C2;
-			result.R1C0 = cos * matrix.R1C0 - sin * matrix.R0C0;
-			result.R1C1 = cos * matrix.R1C1 - sin * matrix.R0C1;
-			result.R1C2 = cos * matrix.R1C2 - sin * matrix.R0C2;
-			result.R2C0 = matrix.R2C0;
-			result.R2C1 = matrix.R2C1;
-			result.R2C2 = matrix.R2C2;
-		}
-		public static void RotateMatrix(float angle, out Matrix3 result)
-		{
-		float angleRadians = MathHelper.DegreesToRadians(angle);
-			float sin = (float)System.Math.Sin(angleRadians);
-			float cos = (float)System.Math.Cos(angleRadians);
-
-			result.R0C0 = cos;
-			result.R0C1 = sin;
-			result.R0C2 = 0;
-			result.R1C0 = -sin;
-			result.R1C1 = cos;
-			result.R1C2 = 0;
-			result.R2C0 = 0;
-			result.R2C1 = 0;
-			result.R2C2 = 1;
-		}
-
-		public Quaternion ToQuaternion ()
-		{
-		return new Quaternion (ref this);
-		}
-
-		#endregion
-
-		#region Constants
-
-		/// <summary>The identity matrix.</summary>
-		public static readonly Matrix3 Identity = new Matrix3
-		(
-			1, 0, 0,
-			0, 1, 0,
-			0, 0, 1
-		);
-
-		/// <summary>A matrix of all zeros.</summary>
-		public static readonly Matrix3 Zero = new Matrix3
-		(
-			0, 0, 0,
-			0, 0, 0,
-			0, 0, 0
-		);
-
-		#endregion
-
-		#region HashCode
-
-		/// <summary>Returns the hash code for this instance.</summary>
-		/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
-		public override int GetHashCode()
-		{
-			return
-				R0C0.GetHashCode() ^ R0C1.GetHashCode() ^ R0C2.GetHashCode() ^
-				R1C0.GetHashCode() ^ R1C1.GetHashCode() ^ R1C2.GetHashCode() ^
-				R2C0.GetHashCode() ^ R2C1.GetHashCode() ^ R2C2.GetHashCode();
-		}
-
-		#endregion
-
-		#region String
-
-		/// <summary>Returns the fully qualified type name of this instance.</summary>
-		/// <returns>A System.String containing left fully qualified type name.</returns>
-		public override string ToString()
-		{
-			return String.Format(
-				"|{00}, {01}, {02}|\n" +
-				"|{03}, {04}, {05}|\n" +
-				"|{06}, {07}, {08}|\n",
-				R0C0, R0C1, R0C2,
-				R1C0, R1C1, R1C2,
-				R2C0, R2C1, R2C2);
-		}
-
-		#endregion
-	}
-	#pragma warning restore 3019
+    // Todo: Remove this warning when the code goes public.
+    #pragma warning disable 3019
+    [StructLayout(LayoutKind.Sequential)]
+    public struct Matrix3 : IEquatable<Matrix3>
+    {
+        #region Fields & Access
+
+        /// <summary>Row 0, Column 0</summary>
+        public float R0C0;
+
+        /// <summary>Row 0, Column 1</summary>
+        public float R0C1;
+
+        /// <summary>Row 0, Column 2</summary>
+        public float R0C2;
+
+        /// <summary>Row 1, Column 0</summary>
+        public float R1C0;
+
+        /// <summary>Row 1, Column 1</summary>
+        public float R1C1;
+
+        /// <summary>Row 1, Column 2</summary>
+        public float R1C2;
+
+        /// <summary>Row 2, Column 0</summary>
+        public float R2C0;
+
+        /// <summary>Row 2, Column 1</summary>
+        public float R2C1;
+
+        /// <summary>Row 2, Column 2</summary>
+        public float R2C2;
+
+        /// <summary>Gets the component at the given row and column in the matrix.</summary>
+        /// <param name="row">The row of the matrix.</param>
+        /// <param name="column">The column of the matrix.</param>
+        /// <returns>The component at the given row and column in the matrix.</returns>
+        public float this[int row, int column]
+        {
+            get
+            {
+                switch( row )
+                {
+                    case 0:
+                        switch (column)
+                        {
+                            case 0: return R0C0;
+                            case 1: return R0C1;
+                            case 2: return R0C2;
+                        }
+                        break;
+
+                    case 1:
+                        switch (column)
+                        {
+                            case 0: return R1C0;
+                            case 1: return R1C1;
+                            case 2: return R1C2;
+                        }
+                        break;
+
+                    case 2:
+                        switch (column)
+                        {
+                            case 0: return R2C0;
+                            case 1: return R2C1;
+                            case 2: return R2C2;
+                        }
+                        break;
+                }
+
+                throw new IndexOutOfRangeException();
+            }
+            set
+            {
+                switch( row )
+                {
+                    case 0:
+                        switch (column)
+                        {
+                            case 0: R0C0 = value; return;
+                            case 1: R0C1 = value; return;
+                            case 2: R0C2 = value; return;
+                        }
+                        break;
+
+                    case 1:
+                        switch (column)
+                        {
+                            case 0: R1C0 = value; return;
+                            case 1: R1C1 = value; return;
+                            case 2: R1C2 = value; return;
+                        }
+                        break;
+
+                    case 2:
+                        switch (column)
+                        {
+                            case 0: R2C0 = value; return;
+                            case 1: R2C1 = value; return;
+                            case 2: R2C2 = value; return;
+                        }
+                        break;
+                }
+
+                throw new IndexOutOfRangeException();
+            }
+        }
+
+        /// <summary>Gets the component at the index into the matrix.</summary>
+        /// <param name="index">The index into the components of the matrix.</param>
+        /// <returns>The component at the given index into the matrix.</returns>
+        public float this[int index]
+        {
+            get
+            {
+                switch (index)
+                {
+                    case 0: return R0C0;
+                    case 1: return R0C1;
+                    case 2: return R0C2;
+                    case 3: return R1C0;
+                    case 4: return R1C1;
+                    case 5: return R1C2;
+                    case 6: return R2C0;
+                    case 7: return R2C1;
+                    case 8: return R2C2;
+                    default: throw new IndexOutOfRangeException();
+                }
+            }
+            set
+            {
+                switch (index)
+                {
+                    case 0: R0C0 = value; return;
+                    case 1: R0C1 = value; return;
+                    case 2: R0C2 = value; return;
+                    case 3: R1C0 = value; return;
+                    case 4: R1C1 = value; return;
+                    case 5: R1C2 = value; return;
+                    case 6: R2C0 = value; return;
+                    case 7: R2C1 = value; return;
+                    case 8: R2C2 = value; return;
+                    default: throw new IndexOutOfRangeException();
+                }
+            }
+        }
+
+        /// <summary>Converts the matrix into an IntPtr.</summary>
+        /// <param name="matrix">The matrix to convert.</param>
+        /// <returns>An IntPtr for the matrix.</returns>
+        public static explicit operator IntPtr(Matrix3 matrix)
+        {
+            unsafe
+            {
+                return (IntPtr)(&matrix.R0C0);
+            }
+        }
+
+        /// <summary>Converts the matrix into left float*.</summary>
+        /// <param name="matrix">The matrix to convert.</param>
+        /// <returns>A float* for the matrix.</returns>
+        [CLSCompliant(false)]
+        unsafe public static explicit operator float*(Matrix3 matrix)
+        {
+            return &matrix.R0C0;
+        }
+
+        /// <summary>Converts the matrix into an array of floats.</summary>
+        /// <param name="matrix">The matrix to convert.</param>
+        /// <returns>An array of floats for the matrix.</returns>
+        public static explicit operator float[](Matrix3 matrix)
+        {
+            return new float[9]
+            {
+                matrix.R0C0,
+                matrix.R0C1,
+                matrix.R0C2,
+                matrix.R1C0,
+                matrix.R1C1,
+                matrix.R1C2,
+                matrix.R2C0,
+                matrix.R2C1,
+                matrix.R2C2
+            };
+        }
+
+        #endregion
+
+        #region Constructors
+
+        /// <summary>Constructs left matrix with the same components as the given matrix.</summary>
+        /// <param name="vector">The matrix whose components to copy.</param>
+        public Matrix3(ref Matrix3 matrix)
+        {
+            this.R0C0 = matrix.R0C0;
+            this.R0C1 = matrix.R0C1;
+            this.R0C2 = matrix.R0C2;
+            this.R1C0 = matrix.R1C0;
+            this.R1C1 = matrix.R1C1;
+            this.R1C2 = matrix.R1C2;
+            this.R2C0 = matrix.R2C0;
+            this.R2C1 = matrix.R2C1;
+            this.R2C2 = matrix.R2C2;
+        }
+
+        /// <summary>Constructs left matrix with the given values.</summary>
+        /// <param name="r0c0">The value for row 0 column 0.</param>
+        /// <param name="r0c1">The value for row 0 column 1.</param>
+        /// <param name="r0c2">The value for row 0 column 2.</param>
+        /// <param name="r1c0">The value for row 1 column 0.</param>
+        /// <param name="r1c1">The value for row 1 column 1.</param>
+        /// <param name="r1c2">The value for row 1 column 2.</param>
+        /// <param name="r2c0">The value for row 2 column 0.</param>
+        /// <param name="r2c1">The value for row 2 column 1.</param>
+        /// <param name="r2c2">The value for row 2 column 2.</param>
+        public Matrix3
+        (
+            float r0c0,
+            float r0c1,
+            float r0c2,
+            float r1c0,
+            float r1c1,
+            float r1c2,
+            float r2c0,
+            float r2c1,
+            float r2c2
+        )
+        {
+            this.R0C0 = r0c0;
+            this.R0C1 = r0c1;
+            this.R0C2 = r0c2;
+            this.R1C0 = r1c0;
+            this.R1C1 = r1c1;
+            this.R1C2 = r1c2;
+            this.R2C0 = r2c0;
+            this.R2C1 = r2c1;
+            this.R2C2 = r2c2;
+        }
+
+        /// <summary>Constructs left matrix from the given array of float-precision floating-point numbers.</summary>
+        /// <param name="floatArray">The array of floats for the components of the matrix.</param>
+        public Matrix3(float[] floatArray)
+        {
+            if (floatArray == null || floatArray.GetLength(0) < 9) throw new InvalidOperationException();
+
+            this.R0C0 = floatArray[0];
+            this.R0C1 = floatArray[1];
+            this.R0C2 = floatArray[2];
+            this.R1C0 = floatArray[3];
+            this.R1C1 = floatArray[4];
+            this.R1C2 = floatArray[5];
+            this.R2C0 = floatArray[6];
+            this.R2C1 = floatArray[7];
+            this.R2C2 = floatArray[8];
+        }
+
+        #endregion
+
+        #region Equality
+
+        /// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
+        /// <param name="matrix">The OpenTK.Matrix3 structure to compare with.</param>
+        /// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
+        [CLSCompliant(false)]
+        public bool Equals(Matrix3 matrix)
+        {
+            return
+                R0C0 == matrix.R0C0 &&
+                R0C1 == matrix.R0C1 &&
+                R0C2 == matrix.R0C2 &&
+                R1C0 == matrix.R1C0 &&
+                R1C1 == matrix.R1C1 &&
+                R1C2 == matrix.R1C2 &&
+                R2C0 == matrix.R2C0 &&
+                R2C1 == matrix.R2C1 &&
+                R2C2 == matrix.R2C2;
+        }
+
+        /// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
+        /// <param name="matrix">The OpenTK.Matrix3 structure to compare to.</param>
+        /// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
+        public bool Equals(ref Matrix3 matrix)
+        {
+            return
+                R0C0 == matrix.R0C0 &&
+                R0C1 == matrix.R0C1 &&
+                R0C2 == matrix.R0C2 &&
+                R1C0 == matrix.R1C0 &&
+                R1C1 == matrix.R1C1 &&
+                R1C2 == matrix.R1C2 &&
+                R2C0 == matrix.R2C0 &&
+                R2C1 == matrix.R2C1 &&
+                R2C2 == matrix.R2C2;
+        }
+
+        /// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
+        /// <param name="left">The left-hand operand.</param>
+        /// <param name="right">The right-hand operand.</param>
+        /// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
+        public static bool Equals(ref Matrix3 left, ref Matrix3 right)
+        {
+            return
+                left.R0C0 == right.R0C0 &&
+                left.R0C1 == right.R0C1 &&
+                left.R0C2 == right.R0C2 &&
+                left.R1C0 == right.R1C0 &&
+                left.R1C1 == right.R1C1 &&
+                left.R1C2 == right.R1C2 &&
+                left.R2C0 == right.R2C0 &&
+                left.R2C1 == right.R2C1 &&
+                left.R2C2 == right.R2C2;
+        }
+
+        /// <summary>Indicates whether the current matrix is approximately equal to another matrix.</summary>
+        /// <param name="matrix">The OpenTK.Matrix3 structure to compare with.</param>
+        /// <param name="tolerance">The limit below which the matrices are considered equal.</param>
+        /// <returns>true if the current matrix is approximately equal to the matrix parameter; otherwise, false.</returns>
+        public bool EqualsApprox(ref Matrix3 matrix, float tolerance)
+        {
+            return
+                System.Math.Abs(R0C0 - matrix.R0C0) <= tolerance &&
+                System.Math.Abs(R0C1 - matrix.R0C1) <= tolerance &&
+                System.Math.Abs(R0C2 - matrix.R0C2) <= tolerance &&
+                System.Math.Abs(R1C0 - matrix.R1C0) <= tolerance &&
+                System.Math.Abs(R1C1 - matrix.R1C1) <= tolerance &&
+                System.Math.Abs(R1C2 - matrix.R1C2) <= tolerance &&
+                System.Math.Abs(R2C0 - matrix.R2C0) <= tolerance &&
+                System.Math.Abs(R2C1 - matrix.R2C1) <= tolerance &&
+                System.Math.Abs(R2C2 - matrix.R2C2) <= tolerance;
+        }
+
+        /// <summary>Indicates whether the current matrix is approximately equal to another matrix.</summary>
+        /// <param name="left">The left-hand operand.</param>
+        /// <param name="right">The right-hand operand.</param>
+        /// <param name="tolerance">The limit below which the matrices are considered equal.</param>
+        /// <returns>true if the current matrix is approximately equal to the matrix parameter; otherwise, false.</returns>
+        public static bool EqualsApprox(ref Matrix3 left, ref Matrix3 right, float tolerance)
+        {
+            return
+                System.Math.Abs(left.R0C0 - right.R0C0) <= tolerance &&
+                System.Math.Abs(left.R0C1 - right.R0C1) <= tolerance &&
+                System.Math.Abs(left.R0C2 - right.R0C2) <= tolerance &&
+                System.Math.Abs(left.R1C0 - right.R1C0) <= tolerance &&
+                System.Math.Abs(left.R1C1 - right.R1C1) <= tolerance &&
+                System.Math.Abs(left.R1C2 - right.R1C2) <= tolerance &&
+                System.Math.Abs(left.R2C0 - right.R2C0) <= tolerance &&
+                System.Math.Abs(left.R2C1 - right.R2C1) <= tolerance &&
+                System.Math.Abs(left.R2C2 - right.R2C2) <= tolerance;
+        }
+
+        #endregion
+
+        #region Arithmetic Operators
+
+
+        /// <summary>Add left matrix to this matrix.</summary>
+        /// <param name="matrix">The matrix to add.</param>
+        public void Add(ref Matrix3 matrix)
+        {
+            R0C0 = R0C0 + matrix.R0C0;
+            R0C1 = R0C1 + matrix.R0C1;
+            R0C2 = R0C2 + matrix.R0C2;
+            R1C0 = R1C0 + matrix.R1C0;
+            R1C1 = R1C1 + matrix.R1C1;
+            R1C2 = R1C2 + matrix.R1C2;
+            R2C0 = R2C0 + matrix.R2C0;
+            R2C1 = R2C1 + matrix.R2C1;
+            R2C2 = R2C2 + matrix.R2C2;
+        }
+
+        /// <summary>Add left matrix to this matrix.</summary>
+        /// <param name="matrix">The matrix to add.</param>
+        /// <param name="result">The resulting matrix of the addition.</param>
+        public void Add(ref Matrix3 matrix, out Matrix3 result)
+        {
+            result.R0C0 = R0C0 + matrix.R0C0;
+            result.R0C1 = R0C1 + matrix.R0C1;
+            result.R0C2 = R0C2 + matrix.R0C2;
+            result.R1C0 = R1C0 + matrix.R1C0;
+            result.R1C1 = R1C1 + matrix.R1C1;
+            result.R1C2 = R1C2 + matrix.R1C2;
+            result.R2C0 = R2C0 + matrix.R2C0;
+            result.R2C1 = R2C1 + matrix.R2C1;
+            result.R2C2 = R2C2 + matrix.R2C2;
+        }
+
+        /// <summary>Add left matrix to left matrix.</summary>
+        /// <param name="matrix">The matrix on the matrix side of the equation.</param>
+        /// <param name="right">The matrix on the right side of the equation</param>
+        /// <param name="result">The resulting matrix of the addition.</param>
+        public static void Add(ref Matrix3 left, ref Matrix3 right, out Matrix3 result)
+        {
+            result.R0C0 = left.R0C0 + right.R0C0;
+            result.R0C1 = left.R0C1 + right.R0C1;
+            result.R0C2 = left.R0C2 + right.R0C2;
+            result.R1C0 = left.R1C0 + right.R1C0;
+            result.R1C1 = left.R1C1 + right.R1C1;
+            result.R1C2 = left.R1C2 + right.R1C2;
+            result.R2C0 = left.R2C0 + right.R2C0;
+            result.R2C1 = left.R2C1 + right.R2C1;
+            result.R2C2 = left.R2C2 + right.R2C2;
+        }
+
+
+        /// <summary>Subtract left matrix from this matrix.</summary>
+        /// <param name="matrix">The matrix to subtract.</param>
+        public void Subtract(ref Matrix3 matrix)
+        {
+            R0C0 = R0C0 + matrix.R0C0;
+            R0C1 = R0C1 + matrix.R0C1;
+            R0C2 = R0C2 + matrix.R0C2;
+            R1C0 = R1C0 + matrix.R1C0;
+            R1C1 = R1C1 + matrix.R1C1;
+            R1C2 = R1C2 + matrix.R1C2;
+            R2C0 = R2C0 + matrix.R2C0;
+            R2C1 = R2C1 + matrix.R2C1;
+            R2C2 = R2C2 + matrix.R2C2;
+        }
+
+        /// <summary>Subtract left matrix from this matrix.</summary>
+        /// <param name="matrix">The matrix to subtract.</param>
+        /// <param name="result">The resulting matrix of the subtraction.</param>
+        public void Subtract(ref Matrix3 matrix, out Matrix3 result)
+        {
+            result.R0C0 = R0C0 + matrix.R0C0;
+            result.R0C1 = R0C1 + matrix.R0C1;
+            result.R0C2 = R0C2 + matrix.R0C2;
+            result.R1C0 = R1C0 + matrix.R1C0;
+            result.R1C1 = R1C1 + matrix.R1C1;
+            result.R1C2 = R1C2 + matrix.R1C2;
+            result.R2C0 = R2C0 + matrix.R2C0;
+            result.R2C1 = R2C1 + matrix.R2C1;
+            result.R2C2 = R2C2 + matrix.R2C2;
+        }
+
+        /// <summary>Subtract left matrix from left matrix.</summary>
+        /// <param name="matrix">The matrix on the matrix side of the equation.</param>
+        /// <param name="right">The matrix on the right side of the equation</param>
+        /// <param name="result">The resulting matrix of the subtraction.</param>
+        public static void Subtract(ref Matrix3 left, ref Matrix3 right, out Matrix3 result)
+        {
+            result.R0C0 = left.R0C0 + right.R0C0;
+            result.R0C1 = left.R0C1 + right.R0C1;
+            result.R0C2 = left.R0C2 + right.R0C2;
+            result.R1C0 = left.R1C0 + right.R1C0;
+            result.R1C1 = left.R1C1 + right.R1C1;
+            result.R1C2 = left.R1C2 + right.R1C2;
+            result.R2C0 = left.R2C0 + right.R2C0;
+            result.R2C1 = left.R2C1 + right.R2C1;
+            result.R2C2 = left.R2C2 + right.R2C2;
+        }
+
+
+        /// <summary>Multiply left martix times this matrix.</summary>
+        /// <param name="matrix">The matrix to multiply.</param>
+        public void Multiply(ref Matrix3 matrix)
+        {
+            float r0c0 = matrix.R0C0 * R0C0 + matrix.R0C1 * R1C0 + matrix.R0C2 * R2C0;
+            float r0c1 = matrix.R0C0 * R0C1 + matrix.R0C1 * R1C1 + matrix.R0C2 * R2C1;
+            float r0c2 = matrix.R0C0 * R0C2 + matrix.R0C1 * R1C2 + matrix.R0C2 * R2C2;
+
+            float r1c0 = matrix.R1C0 * R0C0 + matrix.R1C1 * R1C0 + matrix.R1C2 * R2C0;
+            float r1c1 = matrix.R1C0 * R0C1 + matrix.R1C1 * R1C1 + matrix.R1C2 * R2C1;
+            float r1c2 = matrix.R1C0 * R0C2 + matrix.R1C1 * R1C2 + matrix.R1C2 * R2C2;
+
+            R2C0 = matrix.R2C0 * R0C0 + matrix.R2C1 * R1C0 + matrix.R2C2 * R2C0;
+            R2C1 = matrix.R2C0 * R0C1 + matrix.R2C1 * R1C1 + matrix.R2C2 * R2C1;
+            R2C2 = matrix.R2C0 * R0C2 + matrix.R2C1 * R1C2 + matrix.R2C2 * R2C2;
+
+
+            R0C0 = r0c0;
+            R0C1 = r0c1;
+            R0C2 = r0c2;
+
+            R1C0 = r1c0;
+            R1C1 = r1c1;
+            R1C2 = r1c2;
+        }
+
+        /// <summary>Multiply matrix times this matrix.</summary>
+        /// <param name="matrix">The matrix to multiply.</param>
+        /// <param name="result">The resulting matrix of the multiplication.</param>
+        public void Multiply(ref Matrix3 matrix, out Matrix3 result)
+        {
+            result.R0C0 = matrix.R0C0 * R0C0 + matrix.R0C1 * R1C0 + matrix.R0C2 * R2C0;
+            result.R0C1 = matrix.R0C0 * R0C1 + matrix.R0C1 * R1C1 + matrix.R0C2 * R2C1;
+            result.R0C2 = matrix.R0C0 * R0C2 + matrix.R0C1 * R1C2 + matrix.R0C2 * R2C2;
+            result.R1C0 = matrix.R1C0 * R0C0 + matrix.R1C1 * R1C0 + matrix.R1C2 * R2C0;
+            result.R1C1 = matrix.R1C0 * R0C1 + matrix.R1C1 * R1C1 + matrix.R1C2 * R2C1;
+            result.R1C2 = matrix.R1C0 * R0C2 + matrix.R1C1 * R1C2 + matrix.R1C2 * R2C2;
+            result.R2C0 = matrix.R2C0 * R0C0 + matrix.R2C1 * R1C0 + matrix.R2C2 * R2C0;
+            result.R2C1 = matrix.R2C0 * R0C1 + matrix.R2C1 * R1C1 + matrix.R2C2 * R2C1;
+            result.R2C2 = matrix.R2C0 * R0C2 + matrix.R2C1 * R1C2 + matrix.R2C2 * R2C2;
+        }
+
+        /// <summary>Multiply left matrix times left matrix.</summary>
+        /// <param name="matrix">The matrix on the matrix side of the equation.</param>
+        /// <param name="right">The matrix on the right side of the equation</param>
+        /// <param name="result">The resulting matrix of the multiplication.</param>
+        public static void Multiply(ref Matrix3 left, ref Matrix3 right, out Matrix3 result)
+        {
+            result.R0C0 = right.R0C0 * left.R0C0 + right.R0C1 * left.R1C0 + right.R0C2 * left.R2C0;
+            result.R0C1 = right.R0C0 * left.R0C1 + right.R0C1 * left.R1C1 + right.R0C2 * left.R2C1;
+            result.R0C2 = right.R0C0 * left.R0C2 + right.R0C1 * left.R1C2 + right.R0C2 * left.R2C2;
+            result.R1C0 = right.R1C0 * left.R0C0 + right.R1C1 * left.R1C0 + right.R1C2 * left.R2C0;
+            result.R1C1 = right.R1C0 * left.R0C1 + right.R1C1 * left.R1C1 + right.R1C2 * left.R2C1;
+            result.R1C2 = right.R1C0 * left.R0C2 + right.R1C1 * left.R1C2 + right.R1C2 * left.R2C2;
+            result.R2C0 = right.R2C0 * left.R0C0 + right.R2C1 * left.R1C0 + right.R2C2 * left.R2C0;
+            result.R2C1 = right.R2C0 * left.R0C1 + right.R2C1 * left.R1C1 + right.R2C2 * left.R2C1;
+            result.R2C2 = right.R2C0 * left.R0C2 + right.R2C1 * left.R1C2 + right.R2C2 * left.R2C2;
+        }
+
+
+        /// <summary>Multiply matrix times this matrix.</summary>
+        /// <param name="matrix">The matrix to multiply.</param>
+        public void Multiply(float scalar)
+        {
+            R0C0 = scalar * R0C0;
+            R0C1 = scalar * R0C1;
+            R0C2 = scalar * R0C2;
+            R1C0 = scalar * R1C0;
+            R1C1 = scalar * R1C1;
+            R1C2 = scalar * R1C2;
+            R2C0 = scalar * R2C0;
+            R2C1 = scalar * R2C1;
+            R2C2 = scalar * R2C2;
+        }
+
+        /// <summary>Multiply matrix times this matrix.</summary>
+        /// <param name="matrix">The matrix to multiply.</param>
+        /// <param name="result">The resulting matrix of the multiplication.</param>
+        public void Multiply(float scalar, out Matrix3 result)
+        {
+            result.R0C0 = scalar * R0C0;
+            result.R0C1 = scalar * R0C1;
+            result.R0C2 = scalar * R0C2;
+            result.R1C0 = scalar * R1C0;
+            result.R1C1 = scalar * R1C1;
+            result.R1C2 = scalar * R1C2;
+            result.R2C0 = scalar * R2C0;
+            result.R2C1 = scalar * R2C1;
+            result.R2C2 = scalar * R2C2;
+        }
+
+        /// <summary>Multiply left matrix times left matrix.</summary>
+        /// <param name="matrix">The matrix on the matrix side of the equation.</param>
+        /// <param name="right">The matrix on the right side of the equation</param>
+        /// <param name="result">The resulting matrix of the multiplication.</param>
+        public static void Multiply(ref Matrix3 matrix, float scalar, out Matrix3 result)
+        {
+            result.R0C0 = scalar * matrix.R0C0;
+            result.R0C1 = scalar * matrix.R0C1;
+            result.R0C2 = scalar * matrix.R0C2;
+            result.R1C0 = scalar * matrix.R1C0;
+            result.R1C1 = scalar * matrix.R1C1;
+            result.R1C2 = scalar * matrix.R1C2;
+            result.R2C0 = scalar * matrix.R2C0;
+            result.R2C1 = scalar * matrix.R2C1;
+            result.R2C2 = scalar * matrix.R2C2;
+        }
+
+
+        #endregion
+
+        #region Functions
+
+        public float Determinant
+        {
+            get
+            {
+                return R0C0 * R1C1 * R2C2 - R0C0 * R1C2 * R2C1 - R0C1 * R1C0 * R2C2 + R0C2 * R1C0 * R2C1 + R0C1 * R1C2 * R2C0 - R0C2 * R1C1 * R2C0;
+            }
+        }
+
+        public void Transpose()
+        {
+            MathHelper.Swap(ref R0C1, ref R1C0);
+            MathHelper.Swap(ref R0C2, ref R2C0);
+            MathHelper.Swap(ref R1C2, ref R2C1);
+        }
+        public void Transpose(out Matrix3 result)
+        {
+            result.R0C0 = R0C0;
+            result.R0C1 = R1C0;
+            result.R0C2 = R2C0;
+            result.R1C0 = R0C1;
+            result.R1C1 = R1C1;
+            result.R1C2 = R2C1;
+            result.R2C0 = R0C2;
+            result.R2C1 = R1C2;
+            result.R2C2 = R2C2;
+        }
+        public static void Transpose(ref Matrix3 matrix, out Matrix3 result)
+        {
+            result.R0C0 = matrix.R0C0;
+            result.R0C1 = matrix.R1C0;
+            result.R0C2 = matrix.R2C0;
+            result.R1C0 = matrix.R0C1;
+            result.R1C1 = matrix.R1C1;
+            result.R1C2 = matrix.R2C1;
+            result.R2C0 = matrix.R0C2;
+            result.R2C1 = matrix.R1C2;
+            result.R2C2 = matrix.R2C2;
+        }
+
+        #endregion
+
+        #region Transformation Functions
+
+        public void Transform(ref Vector3 vector)
+        {
+            float x = R0C0 * vector.X + R0C1 * vector.Y + R0C2 * vector.Z;
+            float y = R1C0 * vector.X + R1C1 * vector.Y + R1C2 * vector.Z;
+            vector.Z = R2C0 * vector.X + R2C1 * vector.Y + R2C2 * vector.Z;
+            vector.X = x;
+            vector.Y = y;
+        }
+        public static void Transform(ref Matrix3 matrix, ref Vector3 vector)
+        {
+            float x = matrix.R0C0 * vector.X + matrix.R0C1 * vector.Y + matrix.R0C2 * vector.Z;
+            float y = matrix.R1C0 * vector.X + matrix.R1C1 * vector.Y + matrix.R1C2 * vector.Z;
+            vector.Z = matrix.R2C0 * vector.X + matrix.R2C1 * vector.Y + matrix.R2C2 * vector.Z;
+            vector.X = x;
+            vector.Y = y;
+        }
+        public void Transform(ref Vector3 vector, out Vector3 result)
+        {
+            result.X = R0C0 * vector.X + R0C1 * vector.Y + R0C2 * vector.Z;
+            result.Y = R1C0 * vector.X + R1C1 * vector.Y + R1C2 * vector.Z;
+            result.Z = R2C0 * vector.X + R2C1 * vector.Y + R2C2 * vector.Z;
+        }
+        public static void Transform(ref Matrix3 matrix, ref Vector3 vector, out Vector3 result)
+        {
+            result.X = matrix.R0C0 * vector.X + matrix.R0C1 * vector.Y + matrix.R0C2 * vector.Z;
+            result.Y = matrix.R1C0 * vector.X + matrix.R1C1 * vector.Y + matrix.R1C2 * vector.Z;
+            result.Z = matrix.R2C0 * vector.X + matrix.R2C1 * vector.Y + matrix.R2C2 * vector.Z;
+        }
+
+        public void Rotate(float angle)
+        {
+        float angleRadians = MathHelper.DegreesToRadians (angle);
+            float sin = (float)System.Math.Sin(angleRadians);
+            float cos = (float)System.Math.Cos(angleRadians);
+
+            float r0c0 = cos * R0C0 + sin * R1C0;
+            float r0c1 = cos * R0C1 + sin * R1C1;
+            float r0c2 = cos * R0C2 + sin * R1C2;
+
+            R1C0 = cos * R1C0 - sin * R0C0;
+            R1C1 = cos * R1C1 - sin * R0C1;
+            R1C2 = cos * R1C2 - sin * R0C2;
+
+            R0C0 = r0c0;
+            R0C1 = r0c1;
+            R0C2 = r0c2;
+        }
+        public void Rotate(float angle, out Matrix3 result)
+        {
+        float angleRadians = MathHelper.DegreesToRadians (angle);
+            float sin = (float)System.Math.Sin(angleRadians);
+            float cos = (float)System.Math.Cos(angleRadians);
+
+            result.R0C0 = cos * R0C0 + sin * R1C0;
+            result.R0C1 = cos * R0C1 + sin * R1C1;
+            result.R0C2 = cos * R0C2 + sin * R1C2;
+            result.R1C0 = cos * R1C0 - sin * R0C0;
+            result.R1C1 = cos * R1C1 - sin * R0C1;
+            result.R1C2 = cos * R1C2 - sin * R0C2;
+            result.R2C0 = R2C0;
+            result.R2C1 = R2C1;
+            result.R2C2 = R2C2;
+        }
+        public static void Rotate(ref Matrix3 matrix, float angle, out Matrix3 result)
+        {
+        float angleRadians = MathHelper.DegreesToRadians (angle);
+            float sin = (float)System.Math.Sin(angleRadians);
+            float cos = (float)System.Math.Cos(angleRadians);
+
+            result.R0C0 = cos * matrix.R0C0 + sin * matrix.R1C0;
+            result.R0C1 = cos * matrix.R0C1 + sin * matrix.R1C1;
+            result.R0C2 = cos * matrix.R0C2 + sin * matrix.R1C2;
+            result.R1C0 = cos * matrix.R1C0 - sin * matrix.R0C0;
+            result.R1C1 = cos * matrix.R1C1 - sin * matrix.R0C1;
+            result.R1C2 = cos * matrix.R1C2 - sin * matrix.R0C2;
+            result.R2C0 = matrix.R2C0;
+            result.R2C1 = matrix.R2C1;
+            result.R2C2 = matrix.R2C2;
+        }
+        public static void RotateMatrix(float angle, out Matrix3 result)
+        {
+        float angleRadians = MathHelper.DegreesToRadians(angle);
+            float sin = (float)System.Math.Sin(angleRadians);
+            float cos = (float)System.Math.Cos(angleRadians);
+
+            result.R0C0 = cos;
+            result.R0C1 = sin;
+            result.R0C2 = 0;
+            result.R1C0 = -sin;
+            result.R1C1 = cos;
+            result.R1C2 = 0;
+            result.R2C0 = 0;
+            result.R2C1 = 0;
+            result.R2C2 = 1;
+        }
+
+        public Quaternion ToQuaternion ()
+        {
+        return new Quaternion (ref this);
+        }
+
+        #endregion
+
+        #region Constants
+
+        /// <summary>The identity matrix.</summary>
+        public static readonly Matrix3 Identity = new Matrix3
+        (
+            1, 0, 0,
+            0, 1, 0,
+            0, 0, 1
+        );
+
+        /// <summary>A matrix of all zeros.</summary>
+        public static readonly Matrix3 Zero = new Matrix3
+        (
+            0, 0, 0,
+            0, 0, 0,
+            0, 0, 0
+        );
+
+        #endregion
+
+        #region HashCode
+
+        /// <summary>Returns the hash code for this instance.</summary>
+        /// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
+        public override int GetHashCode()
+        {
+            return
+                R0C0.GetHashCode() ^ R0C1.GetHashCode() ^ R0C2.GetHashCode() ^
+                R1C0.GetHashCode() ^ R1C1.GetHashCode() ^ R1C2.GetHashCode() ^
+                R2C0.GetHashCode() ^ R2C1.GetHashCode() ^ R2C2.GetHashCode();
+        }
+
+        #endregion
+
+        #region String
+
+        /// <summary>Returns the fully qualified type name of this instance.</summary>
+        /// <returns>A System.String containing left fully qualified type name.</returns>
+        public override string ToString()
+        {
+            return String.Format(
+                "|{00}, {01}, {02}|\n" +
+                "|{03}, {04}, {05}|\n" +
+                "|{06}, {07}, {08}|\n",
+                R0C0, R0C1, R0C2,
+                R1C0, R1C1, R1C2,
+                R2C0, R2C1, R2C2);
+        }
+
+        #endregion
+    }
+    #pragma warning restore 3019
 }

+ 1191 - 1191
Script/AtomicNET/AtomicNET/Math/Matrix4.cs

@@ -27,1196 +27,1196 @@ using System.Runtime.InteropServices;
 
 namespace AtomicEngine
 {
-	/// <summary>
-	/// Represents a 4x4 Matrix
-	/// </summary>
-	[StructLayout(LayoutKind.Sequential)]
-	public struct Matrix4 : IEquatable<Matrix4>
-	{
-		#region Fields
-
-		/// <summary>
-		/// Top row of the matrix
-		/// </summary>
-		public Vector4 Row0;
-		/// <summary>
-		/// 2nd row of the matrix
-		/// </summary>
-		public Vector4 Row1;
-		/// <summary>
-		/// 3rd row of the matrix
-		/// </summary>
-		public Vector4 Row2;
-		/// <summary>
-		/// Bottom row of the matrix
-		/// </summary>
-		public Vector4 Row3;
+    /// <summary>
+    /// Represents a 4x4 Matrix
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct Matrix4 : IEquatable<Matrix4>
+    {
+        #region Fields
+
+        /// <summary>
+        /// Top row of the matrix
+        /// </summary>
+        public Vector4 Row0;
+        /// <summary>
+        /// 2nd row of the matrix
+        /// </summary>
+        public Vector4 Row1;
+        /// <summary>
+        /// 3rd row of the matrix
+        /// </summary>
+        public Vector4 Row2;
+        /// <summary>
+        /// Bottom row of the matrix
+        /// </summary>
+        public Vector4 Row3;
  
-		/// <summary>
-		/// The identity matrix
-		/// </summary>
-		public static Matrix4 Identity = new Matrix4(Vector4.UnitX, Vector4.UnitY, Vector4.UnitZ, Vector4.UnitW);
-
-		#endregion
-
-		#region Constructors
-
-		/// <summary>
-		/// Constructs a new instance.
-		/// </summary>
-		/// <param name="row0">Top row of the matrix</param>
-		/// <param name="row1">Second row of the matrix</param>
-		/// <param name="row2">Third row of the matrix</param>
-		/// <param name="row3">Bottom row of the matrix</param>
-		public Matrix4(Vector4 row0, Vector4 row1, Vector4 row2, Vector4 row3)
-		{
-			Row0 = row0;
-			Row1 = row1;
-			Row2 = row2;
-			Row3 = row3;
-		}
-
-		/// <summary>
-		/// Constructs a new instance.
-		/// </summary>
-		/// <param name="m00">First item of the first row of the matrix.</param>
-		/// <param name="m01">Second item of the first row of the matrix.</param>
-		/// <param name="m02">Third item of the first row of the matrix.</param>
-		/// <param name="m03">Fourth item of the first row of the matrix.</param>
-		/// <param name="m10">First item of the second row of the matrix.</param>
-		/// <param name="m11">Second item of the second row of the matrix.</param>
-		/// <param name="m12">Third item of the second row of the matrix.</param>
-		/// <param name="m13">Fourth item of the second row of the matrix.</param>
-		/// <param name="m20">First item of the third row of the matrix.</param>
-		/// <param name="m21">Second item of the third row of the matrix.</param>
-		/// <param name="m22">Third item of the third row of the matrix.</param>
-		/// <param name="m23">First item of the third row of the matrix.</param>
-		/// <param name="m30">Fourth item of the fourth row of the matrix.</param>
-		/// <param name="m31">Second item of the fourth row of the matrix.</param>
-		/// <param name="m32">Third item of the fourth row of the matrix.</param>
-		/// <param name="m33">Fourth item of the fourth row of the matrix.</param>
-		public Matrix4(
-			float m00, float m01, float m02, float m03,
-			float m10, float m11, float m12, float m13,
-			float m20, float m21, float m22, float m23,
-			float m30, float m31, float m32, float m33)
-		{
-			Row0 = new Vector4(m00, m01, m02, m03);
-			Row1 = new Vector4(m10, m11, m12, m13);
-			Row2 = new Vector4(m20, m21, m22, m23);
-			Row3 = new Vector4(m30, m31, m32, m33);
-		}
-
-		#endregion
-
-		#region Public Members
-
-		#region Properties
-
-		/// <summary>
-		/// The determinant of this matrix
-		/// </summary>
-		public float Determinant
-		{
-			get
-			{
-				return
-					Row0.X * Row1.Y * Row2.Z * Row3.W - Row0.X * Row1.Y * Row2.W * Row3.Z + Row0.X * Row1.Z * Row2.W * Row3.Y - Row0.X * Row1.Z * Row2.Y * Row3.W
-				  + Row0.X * Row1.W * Row2.Y * Row3.Z - Row0.X * Row1.W * Row2.Z * Row3.Y - Row0.Y * Row1.Z * Row2.W * Row3.X + Row0.Y * Row1.Z * Row2.X * Row3.W
-				  - Row0.Y * Row1.W * Row2.X * Row3.Z + Row0.Y * Row1.W * Row2.Z * Row3.X - Row0.Y * Row1.X * Row2.Z * Row3.W + Row0.Y * Row1.X * Row2.W * Row3.Z
-				  + Row0.Z * Row1.W * Row2.X * Row3.Y - Row0.Z * Row1.W * Row2.Y * Row3.X + Row0.Z * Row1.X * Row2.Y * Row3.W - Row0.Z * Row1.X * Row2.W * Row3.Y
-				  + Row0.Z * Row1.Y * Row2.W * Row3.X - Row0.Z * Row1.Y * Row2.X * Row3.W - Row0.W * Row1.X * Row2.Y * Row3.Z + Row0.W * Row1.X * Row2.Z * Row3.Y
-				  - Row0.W * Row1.Y * Row2.Z * Row3.X + Row0.W * Row1.Y * Row2.X * Row3.Z - Row0.W * Row1.Z * Row2.X * Row3.Y + Row0.W * Row1.Z * Row2.Y * Row3.X;
-			}
-		}
-
-		/// <summary>
-		/// The first column of this matrix
-		/// </summary>
-		public Vector4 Column0
-		{
-			get { return new Vector4(Row0.X, Row1.X, Row2.X, Row3.X); }
-		}
-
-		/// <summary>
-		/// The second column of this matrix
-		/// </summary>
-		public Vector4 Column1
-		{
-			get { return new Vector4(Row0.Y, Row1.Y, Row2.Y, Row3.Y); }
-		}
-
-		/// <summary>
-		/// The third column of this matrix
-		/// </summary>
-		public Vector4 Column2
-		{
-			get { return new Vector4(Row0.Z, Row1.Z, Row2.Z, Row3.Z); }
-		}
-
-		/// <summary>
-		/// The fourth column of this matrix
-		/// </summary>
-		public Vector4 Column3
-		{
-			get { return new Vector4(Row0.W, Row1.W, Row2.W, Row3.W); }
-		}
-
-		/// <summary>
-		/// Gets or sets the value at row 1, column 1 of this instance.
-		/// </summary>
-		public float M11 { get { return Row0.X; } set { Row0.X = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 1, column 2 of this instance.
-		/// </summary>
-		public float M12 { get { return Row0.Y; } set { Row0.Y = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 1, column 3 of this instance.
-		/// </summary>
-		public float M13 { get { return Row0.Z; } set { Row0.Z = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 1, column 4 of this instance.
-		/// </summary>
-		public float M14 { get { return Row0.W; } set { Row0.W = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 2, column 1 of this instance.
-		/// </summary>
-		public float M21 { get { return Row1.X; } set { Row1.X = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 2, column 2 of this instance.
-		/// </summary>
-		public float M22 { get { return Row1.Y; } set { Row1.Y = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 2, column 3 of this instance.
-		/// </summary>
-		public float M23 { get { return Row1.Z; } set { Row1.Z = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 2, column 4 of this instance.
-		/// </summary>
-		public float M24 { get { return Row1.W; } set { Row1.W = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 3, column 1 of this instance.
-		/// </summary>
-		public float M31 { get { return Row2.X; } set { Row2.X = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 3, column 2 of this instance.
-		/// </summary>
-		public float M32 { get { return Row2.Y; } set { Row2.Y = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 3, column 3 of this instance.
-		/// </summary>
-		public float M33 { get { return Row2.Z; } set { Row2.Z = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 3, column 4 of this instance.
-		/// </summary>
-		public float M34 { get { return Row2.W; } set { Row2.W = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 4, column 1 of this instance.
-		/// </summary>
-		public float M41 { get { return Row3.X; } set { Row3.X = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 4, column 2 of this instance.
-		/// </summary>
-		public float M42 { get { return Row3.Y; } set { Row3.Y = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 4, column 3 of this instance.
-		/// </summary>
-		public float M43 { get { return Row3.Z; } set { Row3.Z = value; } }
-
-		/// <summary>
-		/// Gets or sets the value at row 4, column 4 of this instance.
-		/// </summary>
-		public float M44 { get { return Row3.W; } set { Row3.W = value; } }
-
-		#endregion
-
-		#region Instance
-
-		#region public void Invert()
-
-		/// <summary>
-		/// Converts this instance into its inverse.
-		/// </summary>
-		public void Invert()
-		{
-			this = Matrix4.Invert(this);
-		}
-
-		#endregion
-
-		#region public void Transpose()
-
-		/// <summary>
-		/// Converts this instance into its transpose.
-		/// </summary>
-		public void Transpose()
-		{
-			this = Matrix4.Transpose(this);
-		}
-
-		#endregion
-
-		#endregion
-
-		#region Static
-		
-		#region CreateFromAxisAngle
-		
-		/// <summary>
-		/// Build a rotation matrix from the specified axis/angle rotation.
-		/// </summary>
-		/// <param name="axis">The axis to rotate about.</param>
-		/// <param name="angle">Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).</param>
-		/// <param name="result">A matrix instance.</param>
-		public static void CreateFromAxisAngle(Vector3 axis, float angle, out Matrix4 result)
-		{
-			float cos = (float)System.Math.Cos(-angle);
-			float sin = (float)System.Math.Sin(-angle);
-			float t = 1.0f - cos;
-
-			axis.Normalize();
-
-			result = new Matrix4(t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0f,
-								 t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0f,
-								 t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0f,
-								 0, 0, 0, 1);
-		}
-		
-		/// <summary>
-		/// Build a rotation matrix from the specified axis/angle rotation.
-		/// </summary>
-		/// <param name="axis">The axis to rotate about.</param>
-		/// <param name="angle">Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).</param>
-		/// <returns>A matrix instance.</returns>
-		public static Matrix4 CreateFromAxisAngle(Vector3 axis, float angle)
-		{
-			Matrix4 result;
-			CreateFromAxisAngle(axis, angle, out result);
-			return result;
-		}
-		
-		#endregion
-
-		#region CreateRotation[XYZ]
-
-		/// <summary>
-		/// Builds a rotation matrix for a rotation around the x-axis.
-		/// </summary>
-		/// <param name="angle">The counter-clockwise angle in radians.</param>
-		/// <param name="result">The resulting Matrix4 instance.</param>
-		public static void CreateRotationX(float angle, out Matrix4 result)
-		{
-			float cos = (float)System.Math.Cos(angle);
-			float sin = (float)System.Math.Sin(angle);
-
-			result.Row0 = Vector4.UnitX;
-			result.Row1 = new Vector4(0.0f, cos, sin, 0.0f);
-			result.Row2 = new Vector4(0.0f, -sin, cos, 0.0f);
-			result.Row3 = Vector4.UnitW;
-		}
-
-		/// <summary>
-		/// Builds a rotation matrix for a rotation around the x-axis.
-		/// </summary>
-		/// <param name="angle">The counter-clockwise angle in radians.</param>
-		/// <returns>The resulting Matrix4 instance.</returns>
-		public static Matrix4 CreateRotationX(float angle)
-		{
-			Matrix4 result;
-			CreateRotationX(angle, out result);
-			return result;
-		}
-
-		/// <summary>
-		/// Builds a rotation matrix for a rotation around the y-axis.
-		/// </summary>
-		/// <param name="angle">The counter-clockwise angle in radians.</param>
-		/// <param name="result">The resulting Matrix4 instance.</param>
-		public static void CreateRotationY(float angle, out Matrix4 result)
-		{
-			float cos = (float)System.Math.Cos(angle);
-			float sin = (float)System.Math.Sin(angle);
-
-			result.Row0 = new Vector4(cos, 0.0f, -sin, 0.0f);
-			result.Row1 = Vector4.UnitY;
-			result.Row2 = new Vector4(sin, 0.0f, cos, 0.0f);
-			result.Row3 = Vector4.UnitW;
-		}
-
-		/// <summary>
-		/// Builds a rotation matrix for a rotation around the y-axis.
-		/// </summary>
-		/// <param name="angle">The counter-clockwise angle in radians.</param>
-		/// <returns>The resulting Matrix4 instance.</returns>
-		public static Matrix4 CreateRotationY(float angle)
-		{
-			Matrix4 result;
-			CreateRotationY(angle, out result);
-			return result;
-		}
-
-		/// <summary>
-		/// Builds a rotation matrix for a rotation around the z-axis.
-		/// </summary>
-		/// <param name="angle">The counter-clockwise angle in radians.</param>
-		/// <param name="result">The resulting Matrix4 instance.</param>
-		public static void CreateRotationZ(float angle, out Matrix4 result)
-		{
-			float cos = (float)System.Math.Cos(angle);
-			float sin = (float)System.Math.Sin(angle);
-
-			result.Row0 = new Vector4(cos, sin, 0.0f, 0.0f);
-			result.Row1 = new Vector4(-sin, cos, 0.0f, 0.0f);
-			result.Row2 = Vector4.UnitZ;
-			result.Row3 = Vector4.UnitW;
-		}
-
-		/// <summary>
-		/// Builds a rotation matrix for a rotation around the z-axis.
-		/// </summary>
-		/// <param name="angle">The counter-clockwise angle in radians.</param>
-		/// <returns>The resulting Matrix4 instance.</returns>
-		public static Matrix4 CreateRotationZ(float angle)
-		{
-			Matrix4 result;
-			CreateRotationZ(angle, out result);
-			return result;
-		}
-
-		#endregion
-
-		#region CreateTranslation
-
-		/// <summary>
-		/// Creates a translation matrix.
-		/// </summary>
-		/// <param name="x">X translation.</param>
-		/// <param name="y">Y translation.</param>
-		/// <param name="z">Z translation.</param>
-		/// <param name="result">The resulting Matrix4 instance.</param>
-		public static void CreateTranslation(float x, float y, float z, out Matrix4 result)
-		{
-			result = Identity;
-			result.Row3 = new Vector4(x, y, z, 1);
-		}
-
-		/// <summary>
-		/// Creates a translation matrix.
-		/// </summary>
-		/// <param name="vector">The translation vector.</param>
-		/// <param name="result">The resulting Matrix4 instance.</param>
-		public static void CreateTranslation(ref Vector3 vector, out Matrix4 result)
-		{
-			result = Identity;
-			result.Row3 = new Vector4(vector.X, vector.Y, vector.Z, 1);
-		}
-
-		/// <summary>
-		/// Creates a translation matrix.
-		/// </summary>
-		/// <param name="x">X translation.</param>
-		/// <param name="y">Y translation.</param>
-		/// <param name="z">Z translation.</param>
-		/// <returns>The resulting Matrix4 instance.</returns>
-		public static Matrix4 CreateTranslation(float x, float y, float z)
-		{
-			Matrix4 result;
-			CreateTranslation(x, y, z, out result);
-			return result;
-		}
-
-		/// <summary>
-		/// Creates a translation matrix.
-		/// </summary>
-		/// <param name="vector">The translation vector.</param>
-		/// <returns>The resulting Matrix4 instance.</returns>
-		public static Matrix4 CreateTranslation(Vector3 vector)
-		{
-			Matrix4 result;
-			CreateTranslation(vector.X, vector.Y, vector.Z, out result);
-			return result;
-		}
-
-		#endregion
-
-		#region CreateOrthographic
-
-		/// <summary>
-		/// Creates an orthographic projection matrix.
-		/// </summary>
-		/// <param name="width">The width of the projection volume.</param>
-		/// <param name="height">The height of the projection volume.</param>
-		/// <param name="zNear">The near edge of the projection volume.</param>
-		/// <param name="zFar">The far edge of the projection volume.</param>
-		/// <param name="result">The resulting Matrix4 instance.</param>
-		public static void CreateOrthographic(float width, float height, float zNear, float zFar, out Matrix4 result)
-		{
-			CreateOrthographicOffCenter(-width / 2, width / 2, -height / 2, height / 2, zNear, zFar, out result);
-		}
-
-		/// <summary>
-		/// Creates an orthographic projection matrix.
-		/// </summary>
-		/// <param name="width">The width of the projection volume.</param>
-		/// <param name="height">The height of the projection volume.</param>
-		/// <param name="zNear">The near edge of the projection volume.</param>
-		/// <param name="zFar">The far edge of the projection volume.</param>
-		/// <rereturns>The resulting Matrix4 instance.</rereturns>
-		public static Matrix4 CreateOrthographic(float width, float height, float zNear, float zFar)
-		{
-			Matrix4 result;
-			CreateOrthographicOffCenter(-width / 2, width / 2, -height / 2, height / 2, zNear, zFar, out result);
-			return result;
-		}
-
-		#endregion
-
-		#region CreateOrthographicOffCenter
-
-		/// <summary>
-		/// Creates an orthographic projection matrix.
-		/// </summary>
-		/// <param name="left">The left edge of the projection volume.</param>
-		/// <param name="right">The right edge of the projection volume.</param>
-		/// <param name="bottom">The bottom edge of the projection volume.</param>
-		/// <param name="top">The top edge of the projection volume.</param>
-		/// <param name="zNear">The near edge of the projection volume.</param>
-		/// <param name="zFar">The far edge of the projection volume.</param>
-		/// <param name="result">The resulting Matrix4 instance.</param>
-		public static void CreateOrthographicOffCenter(float left, float right, float bottom, float top, float zNear, float zFar, out Matrix4 result)
-		{
-			result = new Matrix4();
-
-			float invRL = 1 / (right - left);
-			float invTB = 1 / (top - bottom);
-			float invFN = 1 / (zFar - zNear);
-
-			result.M11 = 2 * invRL;
-			result.M22 = 2 * invTB;
-			result.M33 = -2 * invFN;
-
-			result.M41 = -(right + left) * invRL;
-			result.M42 = -(top + bottom) * invTB;
-			result.M43 = -(zFar + zNear) * invFN;
-			result.M44 = 1;
-		}
-
-		/// <summary>
-		/// Creates an orthographic projection matrix.
-		/// </summary>
-		/// <param name="left">The left edge of the projection volume.</param>
-		/// <param name="right">The right edge of the projection volume.</param>
-		/// <param name="bottom">The bottom edge of the projection volume.</param>
-		/// <param name="top">The top edge of the projection volume.</param>
-		/// <param name="zNear">The near edge of the projection volume.</param>
-		/// <param name="zFar">The far edge of the projection volume.</param>
-		/// <returns>The resulting Matrix4 instance.</returns>
-		public static Matrix4 CreateOrthographicOffCenter(float left, float right, float bottom, float top, float zNear, float zFar)
-		{
-			Matrix4 result;
-			CreateOrthographicOffCenter(left, right, bottom, top, zNear, zFar, out result);
-			return result;
-		}
-
-		#endregion
-		
-		#region CreatePerspectiveFieldOfView
-		
-		/// <summary>
-		/// Creates a perspective projection matrix.
-		/// </summary>
-		/// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
-		/// <param name="aspect">Aspect ratio of the view (width / height)</param>
-		/// <param name="zNear">Distance to the near clip plane</param>
-		/// <param name="zFar">Distance to the far clip plane</param>
-		/// <param name="result">A projection matrix that transforms camera space to raster space</param>
-		/// <exception cref="System.ArgumentOutOfRangeException">
-		/// Thrown under the following conditions:
-		/// <list type="bullet">
-		/// <item>fovy is zero, less than zero or larger than Math.PI</item>
-		/// <item>aspect is negative or zero</item>
-		/// <item>zNear is negative or zero</item>
-		/// <item>zFar is negative or zero</item>
-		/// <item>zNear is larger than zFar</item>
-		/// </list>
-		/// </exception>
-		public static void CreatePerspectiveFieldOfView(float fovy, float aspect, float zNear, float zFar, out Matrix4 result)
-		{
-			if (fovy <= 0 || fovy > Math.PI)
-				throw new ArgumentOutOfRangeException("fovy");
-			if (aspect <= 0)
-				throw new ArgumentOutOfRangeException("aspect");
-			if (zNear <= 0)
-				throw new ArgumentOutOfRangeException("zNear");
-			if (zFar <= 0)
-				throw new ArgumentOutOfRangeException("zFar");
-			if (zNear >= zFar)
-				throw new ArgumentOutOfRangeException("zNear");
-			
-			float yMax = zNear * (float)System.Math.Tan(0.5f * fovy);
-			float yMin = -yMax;
-			float xMin = yMin * aspect;
-			float xMax = yMax * aspect;
-
-			CreatePerspectiveOffCenter(xMin, xMax, yMin, yMax, zNear, zFar, out result);
-		}
-		
-		/// <summary>
-		/// Creates a perspective projection matrix.
-		/// </summary>
-		/// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
-		/// <param name="aspect">Aspect ratio of the view (width / height)</param>
-		/// <param name="zNear">Distance to the near clip plane</param>
-		/// <param name="zFar">Distance to the far clip plane</param>
-		/// <returns>A projection matrix that transforms camera space to raster space</returns>
-		/// <exception cref="System.ArgumentOutOfRangeException">
-		/// Thrown under the following conditions:
-		/// <list type="bullet">
-		/// <item>fovy is zero, less than zero or larger than Math.PI</item>
-		/// <item>aspect is negative or zero</item>
-		/// <item>zNear is negative or zero</item>
-		/// <item>zFar is negative or zero</item>
-		/// <item>zNear is larger than zFar</item>
-		/// </list>
-		/// </exception>
-		public static Matrix4 CreatePerspectiveFieldOfView(float fovy, float aspect, float zNear, float zFar)
-		{
-			Matrix4 result;
-			CreatePerspectiveFieldOfView(fovy, aspect, zNear, zFar, out result);
-			return result;
-		}
-		
-		#endregion
-		
-		#region CreatePerspectiveOffCenter
-		
-		/// <summary>
-		/// Creates an perspective projection matrix.
-		/// </summary>
-		/// <param name="left">Left edge of the view frustum</param>
-		/// <param name="right">Right edge of the view frustum</param>
-		/// <param name="bottom">Bottom edge of the view frustum</param>
-		/// <param name="top">Top edge of the view frustum</param>
-		/// <param name="zNear">Distance to the near clip plane</param>
-		/// <param name="zFar">Distance to the far clip plane</param>
-		/// <param name="result">A projection matrix that transforms camera space to raster space</param>
-		/// <exception cref="System.ArgumentOutOfRangeException">
-		/// Thrown under the following conditions:
-		/// <list type="bullet">
-		/// <item>zNear is negative or zero</item>
-		/// <item>zFar is negative or zero</item>
-		/// <item>zNear is larger than zFar</item>
-		/// </list>
-		/// </exception>
-		public static void CreatePerspectiveOffCenter(float left, float right, float bottom, float top, float zNear, float zFar, out Matrix4 result)
-		{
-			if (zNear <= 0)
-				throw new ArgumentOutOfRangeException("zNear");
-			if (zFar <= 0)
-				throw new ArgumentOutOfRangeException("zFar");
-			if (zNear >= zFar)
-				throw new ArgumentOutOfRangeException("zNear");
-			
-			float x = (2.0f * zNear) / (right - left);
-			float y = (2.0f * zNear) / (top - bottom);
-			float a = (right + left) / (right - left);
-			float b = (top + bottom) / (top - bottom);
-			float c = -(zFar + zNear) / (zFar - zNear);
-			float d = -(2.0f * zFar * zNear) / (zFar - zNear);
-			
-			result = new Matrix4(x, 0, 0,  0,
-								 0, y, 0,  0,
-								 a, b, c, -1,
-								 0, 0, d,  0);
-		}
-		
-		/// <summary>
-		/// Creates an perspective projection matrix.
-		/// </summary>
-		/// <param name="left">Left edge of the view frustum</param>
-		/// <param name="right">Right edge of the view frustum</param>
-		/// <param name="bottom">Bottom edge of the view frustum</param>
-		/// <param name="top">Top edge of the view frustum</param>
-		/// <param name="zNear">Distance to the near clip plane</param>
-		/// <param name="zFar">Distance to the far clip plane</param>
-		/// <returns>A projection matrix that transforms camera space to raster space</returns>
-		/// <exception cref="System.ArgumentOutOfRangeException">
-		/// Thrown under the following conditions:
-		/// <list type="bullet">
-		/// <item>zNear is negative or zero</item>
-		/// <item>zFar is negative or zero</item>
-		/// <item>zNear is larger than zFar</item>
-		/// </list>
-		/// </exception>
-		public static Matrix4 CreatePerspectiveOffCenter(float left, float right, float bottom, float top, float zNear, float zFar)
-		{
-			Matrix4 result;
-			CreatePerspectiveOffCenter(left, right, bottom, top, zNear, zFar, out result);
-			return result;
-		}
-		
-		#endregion
-
-		#region Obsolete Functions
-
-		#region Translation Functions
-
-		/// <summary>
-		/// Builds a translation matrix.
-		/// </summary>
-		/// <param name="trans">The translation vector.</param>
-		/// <returns>A new Matrix4 instance.</returns>
-		[Obsolete("Use CreateTranslation instead.")]
-		public static Matrix4 Translation(Vector3 trans)
-		{
-			return Translation(trans.X, trans.Y, trans.Z);
-		}
-
-		/// <summary>
-		/// Build a translation matrix with the given translation
-		/// </summary>
-		/// <param name="x">X translation</param>
-		/// <param name="y">Y translation</param>
-		/// <param name="z">Z translation</param>
-		/// <returns>A Translation matrix</returns>
-		[Obsolete("Use CreateTranslation instead.")]
-		public static Matrix4 Translation(float x, float y, float z)
-		{
-			Matrix4 result = Identity;
-			result.Row3 = new Vector4(x, y, z, 1.0f);
-			return result;
-		}
-
-		#endregion
-
-		#endregion
-
-		#region Scale Functions
-
-		/// <summary>
-		/// Build a scaling matrix
-		/// </summary>
-		/// <param name="scale">Single scale factor for x,y and z axes</param>
-		/// <returns>A scaling matrix</returns>
-		public static Matrix4 Scale(float scale)
-		{
-			return Scale(scale, scale, scale);
-		}
-
-		/// <summary>
-		/// Build a scaling matrix
-		/// </summary>
-		/// <param name="scale">Scale factors for x,y and z axes</param>
-		/// <returns>A scaling matrix</returns>
-		public static Matrix4 Scale(Vector3 scale)
-		{
-			return Scale(scale.X, scale.Y, scale.Z);
-		}
-
-		/// <summary>
-		/// Build a scaling matrix
-		/// </summary>
-		/// <param name="x">Scale factor for x-axis</param>
-		/// <param name="y">Scale factor for y-axis</param>
-		/// <param name="z">Scale factor for z-axis</param>
-		/// <returns>A scaling matrix</returns>
-		public static Matrix4 Scale(float x, float y, float z)
-		{
-			Matrix4 result;
-			result.Row0 = Vector4.UnitX * x;
-			result.Row1 = Vector4.UnitY * y;
-			result.Row2 = Vector4.UnitZ * z;
-			result.Row3 = Vector4.UnitW;
-			return result;
-		}
-
-		#endregion
-
-		#region Rotation Functions
-
-		/// <summary>
-		/// Build a rotation matrix that rotates about the x-axis
-		/// </summary>
-		/// <param name="angle">angle in radians to rotate counter-clockwise around the x-axis</param>
-		/// <returns>A rotation matrix</returns>
-		[Obsolete("Use CreateRotationX instead.")]
-		public static Matrix4 RotateX(float angle)
-		{
-			float cos = (float)System.Math.Cos(angle);
-			float sin = (float)System.Math.Sin(angle);
-
-			Matrix4 result;
-			result.Row0 = Vector4.UnitX;
-			result.Row1 = new Vector4(0.0f, cos, sin, 0.0f);
-			result.Row2 = new Vector4(0.0f, -sin, cos, 0.0f);
-			result.Row3 = Vector4.UnitW;
-			return result;
-		}
-
-		/// <summary>
-		/// Build a rotation matrix that rotates about the y-axis
-		/// </summary>
-		/// <param name="angle">angle in radians to rotate counter-clockwise around the y-axis</param>
-		/// <returns>A rotation matrix</returns>
-		[Obsolete("Use CreateRotationY instead.")]
-		public static Matrix4 RotateY(float angle)
-		{
-			float cos = (float)System.Math.Cos(angle);
-			float sin = (float)System.Math.Sin(angle);
-
-			Matrix4 result;
-			result.Row0 = new Vector4(cos, 0.0f, -sin, 0.0f);
-			result.Row1 = Vector4.UnitY;
-			result.Row2 = new Vector4(sin, 0.0f, cos, 0.0f);
-			result.Row3 = Vector4.UnitW;
-			return result;
-		}
-
-		/// <summary>
-		/// Build a rotation matrix that rotates about the z-axis
-		/// </summary>
-		/// <param name="angle">angle in radians to rotate counter-clockwise around the z-axis</param>
-		/// <returns>A rotation matrix</returns>
-		[Obsolete("Use CreateRotationZ instead.")]
-		public static Matrix4 RotateZ(float angle)
-		{
-			float cos = (float)System.Math.Cos(angle);
-			float sin = (float)System.Math.Sin(angle);
-
-			Matrix4 result;
-			result.Row0 = new Vector4(cos, sin, 0.0f, 0.0f);
-			result.Row1 = new Vector4(-sin, cos, 0.0f, 0.0f);
-			result.Row2 = Vector4.UnitZ;
-			result.Row3 = Vector4.UnitW;
-			return result;
-		}
-
-		/// <summary>
-		/// Build a rotation matrix to rotate about the given axis
-		/// </summary>
-		/// <param name="axis">the axis to rotate about</param>
-		/// <param name="angle">angle in radians to rotate counter-clockwise (looking in the direction of the given axis)</param>
-		/// <returns>A rotation matrix</returns>
-		[Obsolete("Use CreateFromAxisAngle instead.")]
-		public static Matrix4 Rotate(Vector3 axis, float angle)
-		{
-			float cos = (float)System.Math.Cos(-angle);
-			float sin = (float)System.Math.Sin(-angle);
-			float t = 1.0f - cos;
-
-			axis.Normalize();
-
-			Matrix4 result;
-			result.Row0 = new Vector4(t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0f);
-			result.Row1 = new Vector4(t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0f);
-			result.Row2 = new Vector4(t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0f);
-			result.Row3 = Vector4.UnitW;
-			return result;
-		}
-
-		/// <summary>
-		/// Build a rotation matrix from a quaternion
-		/// </summary>
-		/// <param name="q">the quaternion</param>
-		/// <returns>A rotation matrix</returns>
-		public static Matrix4 Rotate(Quaternion q)
-		{
-			Vector3 axis;
-			float angle;
-			q.ToAxisAngle(out axis, out angle);
-			return CreateFromAxisAngle(axis, angle);
-		}
-
-		#endregion
-
-		#region Camera Helper Functions
-
-		/// <summary>
-		/// Build a world space to camera space matrix
-		/// </summary>
-		/// <param name="eye">Eye (camera) position in world space</param>
-		/// <param name="target">Target position in world space</param>
-		/// <param name="up">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
-		/// <returns>A Matrix4 that transforms world space to camera space</returns>
-		public static Matrix4 LookAt(Vector3 eye, Vector3 target, Vector3 up)
-		{
-			Vector3 z = Vector3.Normalize(eye - target);
-			Vector3 x = Vector3.Normalize(Vector3.Cross(up, z));
-			Vector3 y = Vector3.Normalize(Vector3.Cross(z, x));
-
-			Matrix4 rot = new Matrix4(new Vector4(x.X, y.X, z.X, 0.0f),
-										new Vector4(x.Y, y.Y, z.Y, 0.0f),
-										new Vector4(x.Z, y.Z, z.Z, 0.0f),
-										Vector4.UnitW);
-
-			Matrix4 trans = Matrix4.CreateTranslation(-eye);
-
-			return trans * rot;
-		}
-
-		/// <summary>
-		/// Build a world space to camera space matrix
-		/// </summary>
-		/// <param name="eyeX">Eye (camera) position in world space</param>
-		/// <param name="eyeY">Eye (camera) position in world space</param>
-		/// <param name="eyeZ">Eye (camera) position in world space</param>
-		/// <param name="targetX">Target position in world space</param>
-		/// <param name="targetY">Target position in world space</param>
-		/// <param name="targetZ">Target position in world space</param>
-		/// <param name="upX">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
-		/// <param name="upY">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
-		/// <param name="upZ">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
-		/// <returns>A Matrix4 that transforms world space to camera space</returns>
-		public static Matrix4 LookAt(float eyeX, float eyeY, float eyeZ, float targetX, float targetY, float targetZ, float upX, float upY, float upZ)
-		{
-			return LookAt(new Vector3(eyeX, eyeY, eyeZ), new Vector3(targetX, targetY, targetZ), new Vector3(upX, upY, upZ));
-		}
-
-		/// <summary>
-		/// Build a projection matrix
-		/// </summary>
-		/// <param name="left">Left edge of the view frustum</param>
-		/// <param name="right">Right edge of the view frustum</param>
-		/// <param name="bottom">Bottom edge of the view frustum</param>
-		/// <param name="top">Top edge of the view frustum</param>
-		/// <param name="near">Distance to the near clip plane</param>
-		/// <param name="far">Distance to the far clip plane</param>
-		/// <returns>A projection matrix that transforms camera space to raster space</returns>
-		[Obsolete("Use CreatePerspectiveOffCenter instead.")]
-		public static Matrix4 Frustum(float left, float right, float bottom, float top, float near, float far)
-		{
-			float invRL = 1.0f / (right - left);
-			float invTB = 1.0f / (top - bottom);
-			float invFN = 1.0f / (far - near);
-			return new Matrix4(new Vector4(2.0f * near * invRL, 0.0f, 0.0f, 0.0f),
-							   new Vector4(0.0f, 2.0f * near * invTB, 0.0f, 0.0f),
-							   new Vector4((right + left) * invRL, (top + bottom) * invTB, -(far + near) * invFN, -1.0f),
-							   new Vector4(0.0f, 0.0f, -2.0f * far * near * invFN, 0.0f));
-		}
-
-		/// <summary>
-		/// Build a projection matrix
-		/// </summary>
-		/// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
-		/// <param name="aspect">Aspect ratio of the view (width / height)</param>
-		/// <param name="near">Distance to the near clip plane</param>
-		/// <param name="far">Distance to the far clip plane</param>
-		/// <returns>A projection matrix that transforms camera space to raster space</returns>
-		[Obsolete("Use CreatePerspectiveFieldOfView instead.")]
-		public static Matrix4 Perspective(float fovy, float aspect, float near, float far)
-		{
-			float yMax = near * (float)System.Math.Tan(0.5f * fovy);
-			float yMin = -yMax;
-			float xMin = yMin * aspect;
-			float xMax = yMax * aspect;
-
-			return Frustum(xMin, xMax, yMin, yMax, near, far);
-		}
-
-		#endregion
-
-		#region Multiply Functions
-
-		/// <summary>
-		/// Multiplies two instances.
-		/// </summary>
-		/// <param name="left">The left operand of the multiplication.</param>
-		/// <param name="right">The right operand of the multiplication.</param>
-		/// <returns>A new instance that is the result of the multiplication</returns>
-		public static Matrix4 Mult(Matrix4 left, Matrix4 right)
-		{
-			Matrix4 result;
-			Mult(ref left, ref right, out result);
-			return result;
-		}
-
-		/// <summary>
-		/// Multiplies two instances.
-		/// </summary>
-		/// <param name="left">The left operand of the multiplication.</param>
-		/// <param name="right">The right operand of the multiplication.</param>
-		/// <param name="result">A new instance that is the result of the multiplication</param>
-		public static void Mult(ref Matrix4 left, ref Matrix4 right, out Matrix4 result)
-		{
-			result = new Matrix4(
-				left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31 + left.M14 * right.M41,
-				left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32 + left.M14 * right.M42,
-				left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33 + left.M14 * right.M43,
-				left.M11 * right.M14 + left.M12 * right.M24 + left.M13 * right.M34 + left.M14 * right.M44,
-				left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31 + left.M24 * right.M41,
-				left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32 + left.M24 * right.M42,
-				left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33 + left.M24 * right.M43,
-				left.M21 * right.M14 + left.M22 * right.M24 + left.M23 * right.M34 + left.M24 * right.M44,
-				left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31 + left.M34 * right.M41,
-				left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32 + left.M34 * right.M42,
-				left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33 + left.M34 * right.M43,
-				left.M31 * right.M14 + left.M32 * right.M24 + left.M33 * right.M34 + left.M34 * right.M44,
-				left.M41 * right.M11 + left.M42 * right.M21 + left.M43 * right.M31 + left.M44 * right.M41,
-				left.M41 * right.M12 + left.M42 * right.M22 + left.M43 * right.M32 + left.M44 * right.M42,
-				left.M41 * right.M13 + left.M42 * right.M23 + left.M43 * right.M33 + left.M44 * right.M43,
-				left.M41 * right.M14 + left.M42 * right.M24 + left.M43 * right.M34 + left.M44 * right.M44);
-		}
-
-		#endregion
-
-		#region Invert Functions
-
-		/// <summary>
-		/// Calculate the inverse of the given matrix
-		/// </summary>
-		/// <param name="mat">The matrix to invert</param>
-		/// <returns>The inverse of the given matrix if it has one, or the input if it is singular</returns>
-		/// <exception cref="InvalidOperationException">Thrown if the Matrix4 is singular.</exception>
-		public static Matrix4 Invert(Matrix4 mat)
-		{
-			int[] colIdx = { 0, 0, 0, 0 };
-			int[] rowIdx = { 0, 0, 0, 0 };
-			int[] pivotIdx = { -1, -1, -1, -1 };
-
-			// convert the matrix to an array for easy looping
-			float[,] inverse = {{mat.Row0.X, mat.Row0.Y, mat.Row0.Z, mat.Row0.W}, 
-								{mat.Row1.X, mat.Row1.Y, mat.Row1.Z, mat.Row1.W}, 
-								{mat.Row2.X, mat.Row2.Y, mat.Row2.Z, mat.Row2.W}, 
-								{mat.Row3.X, mat.Row3.Y, mat.Row3.Z, mat.Row3.W} };
-			int icol = 0;
-			int irow = 0;
-			for (int i = 0; i < 4; i++)
-			{
-				// Find the largest pivot value
-				float maxPivot = 0.0f;
-				for (int j = 0; j < 4; j++)
-				{
-					if (pivotIdx[j] != 0)
-					{
-						for (int k = 0; k < 4; ++k)
-						{
-							if (pivotIdx[k] == -1)
-							{
-								float absVal = System.Math.Abs(inverse[j, k]);
-								if (absVal > maxPivot)
-								{
-									maxPivot = absVal;
-									irow = j;
-									icol = k;
-								}
-							}
-							else if (pivotIdx[k] > 0)
-							{
-								return mat;
-							}
-						}
-					}
-				}
-
-				++(pivotIdx[icol]);
-
-				// Swap rows over so pivot is on diagonal
-				if (irow != icol)
-				{
-					for (int k = 0; k < 4; ++k)
-					{
-						float f = inverse[irow, k];
-						inverse[irow, k] = inverse[icol, k];
-						inverse[icol, k] = f;
-					}
-				}
-
-				rowIdx[i] = irow;
-				colIdx[i] = icol;
-
-				float pivot = inverse[icol, icol];
-				// check for singular matrix
-				if (pivot == 0.0f)
-				{
-					throw new InvalidOperationException("Matrix is singular and cannot be inverted.");
-					//return mat;
-				}
-
-				// Scale row so it has a unit diagonal
-				float oneOverPivot = 1.0f / pivot;
-				inverse[icol, icol] = 1.0f;
-				for (int k = 0; k < 4; ++k)
-					inverse[icol, k] *= oneOverPivot;
-
-				// Do elimination of non-diagonal elements
-				for (int j = 0; j < 4; ++j)
-				{
-					// check this isn't on the diagonal
-					if (icol != j)
-					{
-						float f = inverse[j, icol];
-						inverse[j, icol] = 0.0f;
-						for (int k = 0; k < 4; ++k)
-							inverse[j, k] -= inverse[icol, k] * f;
-					}
-				}
-			}
-
-			for (int j = 3; j >= 0; --j)
-			{
-				int ir = rowIdx[j];
-				int ic = colIdx[j];
-				for (int k = 0; k < 4; ++k)
-				{
-					float f = inverse[k, ir];
-					inverse[k, ir] = inverse[k, ic];
-					inverse[k, ic] = f;
-				}
-			}
-
-			mat.Row0 = new Vector4(inverse[0, 0], inverse[0, 1], inverse[0, 2], inverse[0, 3]);
-			mat.Row1 = new Vector4(inverse[1, 0], inverse[1, 1], inverse[1, 2], inverse[1, 3]);
-			mat.Row2 = new Vector4(inverse[2, 0], inverse[2, 1], inverse[2, 2], inverse[2, 3]);
-			mat.Row3 = new Vector4(inverse[3, 0], inverse[3, 1], inverse[3, 2], inverse[3, 3]);
-			return mat;
-		}
-
-		#endregion
-
-		#region Transpose
-
-		/// <summary>
-		/// Calculate the transpose of the given matrix
-		/// </summary>
-		/// <param name="mat">The matrix to transpose</param>
-		/// <returns>The transpose of the given matrix</returns>
-		public static Matrix4 Transpose(Matrix4 mat)
-		{
-			return new Matrix4(mat.Column0, mat.Column1, mat.Column2, mat.Column3);
-		}
-
-
-		/// <summary>
-		/// Calculate the transpose of the given matrix
-		/// </summary>
-		/// <param name="mat">The matrix to transpose</param>
-		/// <param name="result">The result of the calculation</param>
-		public static void Transpose(ref Matrix4 mat, out Matrix4 result)
-		{
-			result.Row0 = mat.Column0;
-			result.Row1 = mat.Column1;
-			result.Row2 = mat.Column2;
-			result.Row3 = mat.Column3;
-		}
-
-		#endregion
-
-		#endregion
-
-		#region Operators
-
-		/// <summary>
-		/// Matrix multiplication
-		/// </summary>
-		/// <param name="left">left-hand operand</param>
-		/// <param name="right">right-hand operand</param>
-		/// <returns>A new Matrix44 which holds the result of the multiplication</returns>
-		public static Matrix4 operator *(Matrix4 left, Matrix4 right)
-		{
-			return Matrix4.Mult(left, right);
-		}
-
-		/// <summary>
-		/// Compares two instances for equality.
-		/// </summary>
-		/// <param name="left">The first instance.</param>
-		/// <param name="right">The second instance.</param>
-		/// <returns>True, if left equals right; false otherwise.</returns>
-		public static bool operator ==(Matrix4 left, Matrix4 right)
-		{
-			return left.Equals(right);
-		}
-
-		/// <summary>
-		/// Compares two instances for inequality.
-		/// </summary>
-		/// <param name="left">The first instance.</param>
-		/// <param name="right">The second instance.</param>
-		/// <returns>True, if left does not equal right; false otherwise.</returns>
-		public static bool operator !=(Matrix4 left, Matrix4 right)
-		{
-			return !left.Equals(right);
-		}
-
-		#endregion
-
-		#region Overrides
-
-		#region public override string ToString()
-
-		/// <summary>
-		/// Returns a System.String that represents the current Matrix44.
-		/// </summary>
-		/// <returns></returns>
-		public override string ToString()
-		{
-			return String.Format("{0}\n{1}\n{2}\n{3}", Row0, Row1, Row2, Row3);
-		}
-
-		#endregion
-
-		#region public override int GetHashCode()
-
-		/// <summary>
-		/// Returns the hashcode for this instance.
-		/// </summary>
-		/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
-		public override int GetHashCode()
-		{
-			return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode() ^ Row3.GetHashCode();
-		}
-
-		#endregion
-
-		#region public override bool Equals(object obj)
-
-		/// <summary>
-		/// Indicates whether this instance and a specified object are equal.
-		/// </summary>
-		/// <param name="obj">The object to compare tresult.</param>
-		/// <returns>True if the instances are equal; false otherwise.</returns>
-		public override bool Equals(object obj)
-		{
-			if (!(obj is Matrix4))
-				return false;
-
-			return this.Equals((Matrix4)obj);
-		}
-
-		#endregion
-
-		#endregion
-
-		#endregion
-
-		#region IEquatable<Matrix4> Members
-
-		/// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
-		/// <param name="other">An matrix to compare with this matrix.</param>
-		/// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
-		public bool Equals(Matrix4 other)
-		{
-			return
-				Row0 == other.Row0 &&
-				Row1 == other.Row1 &&
-				Row2 == other.Row2 &&
-				Row3 == other.Row3;
-		}
-
-		#endregion
-	}
+        /// <summary>
+        /// The identity matrix
+        /// </summary>
+        public static Matrix4 Identity = new Matrix4(Vector4.UnitX, Vector4.UnitY, Vector4.UnitZ, Vector4.UnitW);
+
+        #endregion
+
+        #region Constructors
+
+        /// <summary>
+        /// Constructs a new instance.
+        /// </summary>
+        /// <param name="row0">Top row of the matrix</param>
+        /// <param name="row1">Second row of the matrix</param>
+        /// <param name="row2">Third row of the matrix</param>
+        /// <param name="row3">Bottom row of the matrix</param>
+        public Matrix4(Vector4 row0, Vector4 row1, Vector4 row2, Vector4 row3)
+        {
+            Row0 = row0;
+            Row1 = row1;
+            Row2 = row2;
+            Row3 = row3;
+        }
+
+        /// <summary>
+        /// Constructs a new instance.
+        /// </summary>
+        /// <param name="m00">First item of the first row of the matrix.</param>
+        /// <param name="m01">Second item of the first row of the matrix.</param>
+        /// <param name="m02">Third item of the first row of the matrix.</param>
+        /// <param name="m03">Fourth item of the first row of the matrix.</param>
+        /// <param name="m10">First item of the second row of the matrix.</param>
+        /// <param name="m11">Second item of the second row of the matrix.</param>
+        /// <param name="m12">Third item of the second row of the matrix.</param>
+        /// <param name="m13">Fourth item of the second row of the matrix.</param>
+        /// <param name="m20">First item of the third row of the matrix.</param>
+        /// <param name="m21">Second item of the third row of the matrix.</param>
+        /// <param name="m22">Third item of the third row of the matrix.</param>
+        /// <param name="m23">First item of the third row of the matrix.</param>
+        /// <param name="m30">Fourth item of the fourth row of the matrix.</param>
+        /// <param name="m31">Second item of the fourth row of the matrix.</param>
+        /// <param name="m32">Third item of the fourth row of the matrix.</param>
+        /// <param name="m33">Fourth item of the fourth row of the matrix.</param>
+        public Matrix4(
+            float m00, float m01, float m02, float m03,
+            float m10, float m11, float m12, float m13,
+            float m20, float m21, float m22, float m23,
+            float m30, float m31, float m32, float m33)
+        {
+            Row0 = new Vector4(m00, m01, m02, m03);
+            Row1 = new Vector4(m10, m11, m12, m13);
+            Row2 = new Vector4(m20, m21, m22, m23);
+            Row3 = new Vector4(m30, m31, m32, m33);
+        }
+
+        #endregion
+
+        #region Public Members
+
+        #region Properties
+
+        /// <summary>
+        /// The determinant of this matrix
+        /// </summary>
+        public float Determinant
+        {
+            get
+            {
+                return
+                    Row0.X * Row1.Y * Row2.Z * Row3.W - Row0.X * Row1.Y * Row2.W * Row3.Z + Row0.X * Row1.Z * Row2.W * Row3.Y - Row0.X * Row1.Z * Row2.Y * Row3.W
+                  + Row0.X * Row1.W * Row2.Y * Row3.Z - Row0.X * Row1.W * Row2.Z * Row3.Y - Row0.Y * Row1.Z * Row2.W * Row3.X + Row0.Y * Row1.Z * Row2.X * Row3.W
+                  - Row0.Y * Row1.W * Row2.X * Row3.Z + Row0.Y * Row1.W * Row2.Z * Row3.X - Row0.Y * Row1.X * Row2.Z * Row3.W + Row0.Y * Row1.X * Row2.W * Row3.Z
+                  + Row0.Z * Row1.W * Row2.X * Row3.Y - Row0.Z * Row1.W * Row2.Y * Row3.X + Row0.Z * Row1.X * Row2.Y * Row3.W - Row0.Z * Row1.X * Row2.W * Row3.Y
+                  + Row0.Z * Row1.Y * Row2.W * Row3.X - Row0.Z * Row1.Y * Row2.X * Row3.W - Row0.W * Row1.X * Row2.Y * Row3.Z + Row0.W * Row1.X * Row2.Z * Row3.Y
+                  - Row0.W * Row1.Y * Row2.Z * Row3.X + Row0.W * Row1.Y * Row2.X * Row3.Z - Row0.W * Row1.Z * Row2.X * Row3.Y + Row0.W * Row1.Z * Row2.Y * Row3.X;
+            }
+        }
+
+        /// <summary>
+        /// The first column of this matrix
+        /// </summary>
+        public Vector4 Column0
+        {
+            get { return new Vector4(Row0.X, Row1.X, Row2.X, Row3.X); }
+        }
+
+        /// <summary>
+        /// The second column of this matrix
+        /// </summary>
+        public Vector4 Column1
+        {
+            get { return new Vector4(Row0.Y, Row1.Y, Row2.Y, Row3.Y); }
+        }
+
+        /// <summary>
+        /// The third column of this matrix
+        /// </summary>
+        public Vector4 Column2
+        {
+            get { return new Vector4(Row0.Z, Row1.Z, Row2.Z, Row3.Z); }
+        }
+
+        /// <summary>
+        /// The fourth column of this matrix
+        /// </summary>
+        public Vector4 Column3
+        {
+            get { return new Vector4(Row0.W, Row1.W, Row2.W, Row3.W); }
+        }
+
+        /// <summary>
+        /// Gets or sets the value at row 1, column 1 of this instance.
+        /// </summary>
+        public float M11 { get { return Row0.X; } set { Row0.X = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 1, column 2 of this instance.
+        /// </summary>
+        public float M12 { get { return Row0.Y; } set { Row0.Y = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 1, column 3 of this instance.
+        /// </summary>
+        public float M13 { get { return Row0.Z; } set { Row0.Z = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 1, column 4 of this instance.
+        /// </summary>
+        public float M14 { get { return Row0.W; } set { Row0.W = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 2, column 1 of this instance.
+        /// </summary>
+        public float M21 { get { return Row1.X; } set { Row1.X = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 2, column 2 of this instance.
+        /// </summary>
+        public float M22 { get { return Row1.Y; } set { Row1.Y = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 2, column 3 of this instance.
+        /// </summary>
+        public float M23 { get { return Row1.Z; } set { Row1.Z = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 2, column 4 of this instance.
+        /// </summary>
+        public float M24 { get { return Row1.W; } set { Row1.W = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 3, column 1 of this instance.
+        /// </summary>
+        public float M31 { get { return Row2.X; } set { Row2.X = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 3, column 2 of this instance.
+        /// </summary>
+        public float M32 { get { return Row2.Y; } set { Row2.Y = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 3, column 3 of this instance.
+        /// </summary>
+        public float M33 { get { return Row2.Z; } set { Row2.Z = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 3, column 4 of this instance.
+        /// </summary>
+        public float M34 { get { return Row2.W; } set { Row2.W = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 4, column 1 of this instance.
+        /// </summary>
+        public float M41 { get { return Row3.X; } set { Row3.X = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 4, column 2 of this instance.
+        /// </summary>
+        public float M42 { get { return Row3.Y; } set { Row3.Y = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 4, column 3 of this instance.
+        /// </summary>
+        public float M43 { get { return Row3.Z; } set { Row3.Z = value; } }
+
+        /// <summary>
+        /// Gets or sets the value at row 4, column 4 of this instance.
+        /// </summary>
+        public float M44 { get { return Row3.W; } set { Row3.W = value; } }
+
+        #endregion
+
+        #region Instance
+
+        #region public void Invert()
+
+        /// <summary>
+        /// Converts this instance into its inverse.
+        /// </summary>
+        public void Invert()
+        {
+            this = Matrix4.Invert(this);
+        }
+
+        #endregion
+
+        #region public void Transpose()
+
+        /// <summary>
+        /// Converts this instance into its transpose.
+        /// </summary>
+        public void Transpose()
+        {
+            this = Matrix4.Transpose(this);
+        }
+
+        #endregion
+
+        #endregion
+
+        #region Static
+        
+        #region CreateFromAxisAngle
+        
+        /// <summary>
+        /// Build a rotation matrix from the specified axis/angle rotation.
+        /// </summary>
+        /// <param name="axis">The axis to rotate about.</param>
+        /// <param name="angle">Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).</param>
+        /// <param name="result">A matrix instance.</param>
+        public static void CreateFromAxisAngle(Vector3 axis, float angle, out Matrix4 result)
+        {
+            float cos = (float)System.Math.Cos(-angle);
+            float sin = (float)System.Math.Sin(-angle);
+            float t = 1.0f - cos;
+
+            axis.Normalize();
+
+            result = new Matrix4(t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0f,
+                                 t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0f,
+                                 t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0f,
+                                 0, 0, 0, 1);
+        }
+        
+        /// <summary>
+        /// Build a rotation matrix from the specified axis/angle rotation.
+        /// </summary>
+        /// <param name="axis">The axis to rotate about.</param>
+        /// <param name="angle">Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).</param>
+        /// <returns>A matrix instance.</returns>
+        public static Matrix4 CreateFromAxisAngle(Vector3 axis, float angle)
+        {
+            Matrix4 result;
+            CreateFromAxisAngle(axis, angle, out result);
+            return result;
+        }
+        
+        #endregion
+
+        #region CreateRotation[XYZ]
+
+        /// <summary>
+        /// Builds a rotation matrix for a rotation around the x-axis.
+        /// </summary>
+        /// <param name="angle">The counter-clockwise angle in radians.</param>
+        /// <param name="result">The resulting Matrix4 instance.</param>
+        public static void CreateRotationX(float angle, out Matrix4 result)
+        {
+            float cos = (float)System.Math.Cos(angle);
+            float sin = (float)System.Math.Sin(angle);
+
+            result.Row0 = Vector4.UnitX;
+            result.Row1 = new Vector4(0.0f, cos, sin, 0.0f);
+            result.Row2 = new Vector4(0.0f, -sin, cos, 0.0f);
+            result.Row3 = Vector4.UnitW;
+        }
+
+        /// <summary>
+        /// Builds a rotation matrix for a rotation around the x-axis.
+        /// </summary>
+        /// <param name="angle">The counter-clockwise angle in radians.</param>
+        /// <returns>The resulting Matrix4 instance.</returns>
+        public static Matrix4 CreateRotationX(float angle)
+        {
+            Matrix4 result;
+            CreateRotationX(angle, out result);
+            return result;
+        }
+
+        /// <summary>
+        /// Builds a rotation matrix for a rotation around the y-axis.
+        /// </summary>
+        /// <param name="angle">The counter-clockwise angle in radians.</param>
+        /// <param name="result">The resulting Matrix4 instance.</param>
+        public static void CreateRotationY(float angle, out Matrix4 result)
+        {
+            float cos = (float)System.Math.Cos(angle);
+            float sin = (float)System.Math.Sin(angle);
+
+            result.Row0 = new Vector4(cos, 0.0f, -sin, 0.0f);
+            result.Row1 = Vector4.UnitY;
+            result.Row2 = new Vector4(sin, 0.0f, cos, 0.0f);
+            result.Row3 = Vector4.UnitW;
+        }
+
+        /// <summary>
+        /// Builds a rotation matrix for a rotation around the y-axis.
+        /// </summary>
+        /// <param name="angle">The counter-clockwise angle in radians.</param>
+        /// <returns>The resulting Matrix4 instance.</returns>
+        public static Matrix4 CreateRotationY(float angle)
+        {
+            Matrix4 result;
+            CreateRotationY(angle, out result);
+            return result;
+        }
+
+        /// <summary>
+        /// Builds a rotation matrix for a rotation around the z-axis.
+        /// </summary>
+        /// <param name="angle">The counter-clockwise angle in radians.</param>
+        /// <param name="result">The resulting Matrix4 instance.</param>
+        public static void CreateRotationZ(float angle, out Matrix4 result)
+        {
+            float cos = (float)System.Math.Cos(angle);
+            float sin = (float)System.Math.Sin(angle);
+
+            result.Row0 = new Vector4(cos, sin, 0.0f, 0.0f);
+            result.Row1 = new Vector4(-sin, cos, 0.0f, 0.0f);
+            result.Row2 = Vector4.UnitZ;
+            result.Row3 = Vector4.UnitW;
+        }
+
+        /// <summary>
+        /// Builds a rotation matrix for a rotation around the z-axis.
+        /// </summary>
+        /// <param name="angle">The counter-clockwise angle in radians.</param>
+        /// <returns>The resulting Matrix4 instance.</returns>
+        public static Matrix4 CreateRotationZ(float angle)
+        {
+            Matrix4 result;
+            CreateRotationZ(angle, out result);
+            return result;
+        }
+
+        #endregion
+
+        #region CreateTranslation
+
+        /// <summary>
+        /// Creates a translation matrix.
+        /// </summary>
+        /// <param name="x">X translation.</param>
+        /// <param name="y">Y translation.</param>
+        /// <param name="z">Z translation.</param>
+        /// <param name="result">The resulting Matrix4 instance.</param>
+        public static void CreateTranslation(float x, float y, float z, out Matrix4 result)
+        {
+            result = Identity;
+            result.Row3 = new Vector4(x, y, z, 1);
+        }
+
+        /// <summary>
+        /// Creates a translation matrix.
+        /// </summary>
+        /// <param name="vector">The translation vector.</param>
+        /// <param name="result">The resulting Matrix4 instance.</param>
+        public static void CreateTranslation(ref Vector3 vector, out Matrix4 result)
+        {
+            result = Identity;
+            result.Row3 = new Vector4(vector.X, vector.Y, vector.Z, 1);
+        }
+
+        /// <summary>
+        /// Creates a translation matrix.
+        /// </summary>
+        /// <param name="x">X translation.</param>
+        /// <param name="y">Y translation.</param>
+        /// <param name="z">Z translation.</param>
+        /// <returns>The resulting Matrix4 instance.</returns>
+        public static Matrix4 CreateTranslation(float x, float y, float z)
+        {
+            Matrix4 result;
+            CreateTranslation(x, y, z, out result);
+            return result;
+        }
+
+        /// <summary>
+        /// Creates a translation matrix.
+        /// </summary>
+        /// <param name="vector">The translation vector.</param>
+        /// <returns>The resulting Matrix4 instance.</returns>
+        public static Matrix4 CreateTranslation(Vector3 vector)
+        {
+            Matrix4 result;
+            CreateTranslation(vector.X, vector.Y, vector.Z, out result);
+            return result;
+        }
+
+        #endregion
+
+        #region CreateOrthographic
+
+        /// <summary>
+        /// Creates an orthographic projection matrix.
+        /// </summary>
+        /// <param name="width">The width of the projection volume.</param>
+        /// <param name="height">The height of the projection volume.</param>
+        /// <param name="zNear">The near edge of the projection volume.</param>
+        /// <param name="zFar">The far edge of the projection volume.</param>
+        /// <param name="result">The resulting Matrix4 instance.</param>
+        public static void CreateOrthographic(float width, float height, float zNear, float zFar, out Matrix4 result)
+        {
+            CreateOrthographicOffCenter(-width / 2, width / 2, -height / 2, height / 2, zNear, zFar, out result);
+        }
+
+        /// <summary>
+        /// Creates an orthographic projection matrix.
+        /// </summary>
+        /// <param name="width">The width of the projection volume.</param>
+        /// <param name="height">The height of the projection volume.</param>
+        /// <param name="zNear">The near edge of the projection volume.</param>
+        /// <param name="zFar">The far edge of the projection volume.</param>
+        /// <rereturns>The resulting Matrix4 instance.</rereturns>
+        public static Matrix4 CreateOrthographic(float width, float height, float zNear, float zFar)
+        {
+            Matrix4 result;
+            CreateOrthographicOffCenter(-width / 2, width / 2, -height / 2, height / 2, zNear, zFar, out result);
+            return result;
+        }
+
+        #endregion
+
+        #region CreateOrthographicOffCenter
+
+        /// <summary>
+        /// Creates an orthographic projection matrix.
+        /// </summary>
+        /// <param name="left">The left edge of the projection volume.</param>
+        /// <param name="right">The right edge of the projection volume.</param>
+        /// <param name="bottom">The bottom edge of the projection volume.</param>
+        /// <param name="top">The top edge of the projection volume.</param>
+        /// <param name="zNear">The near edge of the projection volume.</param>
+        /// <param name="zFar">The far edge of the projection volume.</param>
+        /// <param name="result">The resulting Matrix4 instance.</param>
+        public static void CreateOrthographicOffCenter(float left, float right, float bottom, float top, float zNear, float zFar, out Matrix4 result)
+        {
+            result = new Matrix4();
+
+            float invRL = 1 / (right - left);
+            float invTB = 1 / (top - bottom);
+            float invFN = 1 / (zFar - zNear);
+
+            result.M11 = 2 * invRL;
+            result.M22 = 2 * invTB;
+            result.M33 = -2 * invFN;
+
+            result.M41 = -(right + left) * invRL;
+            result.M42 = -(top + bottom) * invTB;
+            result.M43 = -(zFar + zNear) * invFN;
+            result.M44 = 1;
+        }
+
+        /// <summary>
+        /// Creates an orthographic projection matrix.
+        /// </summary>
+        /// <param name="left">The left edge of the projection volume.</param>
+        /// <param name="right">The right edge of the projection volume.</param>
+        /// <param name="bottom">The bottom edge of the projection volume.</param>
+        /// <param name="top">The top edge of the projection volume.</param>
+        /// <param name="zNear">The near edge of the projection volume.</param>
+        /// <param name="zFar">The far edge of the projection volume.</param>
+        /// <returns>The resulting Matrix4 instance.</returns>
+        public static Matrix4 CreateOrthographicOffCenter(float left, float right, float bottom, float top, float zNear, float zFar)
+        {
+            Matrix4 result;
+            CreateOrthographicOffCenter(left, right, bottom, top, zNear, zFar, out result);
+            return result;
+        }
+
+        #endregion
+        
+        #region CreatePerspectiveFieldOfView
+        
+        /// <summary>
+        /// Creates a perspective projection matrix.
+        /// </summary>
+        /// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
+        /// <param name="aspect">Aspect ratio of the view (width / height)</param>
+        /// <param name="zNear">Distance to the near clip plane</param>
+        /// <param name="zFar">Distance to the far clip plane</param>
+        /// <param name="result">A projection matrix that transforms camera space to raster space</param>
+        /// <exception cref="System.ArgumentOutOfRangeException">
+        /// Thrown under the following conditions:
+        /// <list type="bullet">
+        /// <item>fovy is zero, less than zero or larger than Math.PI</item>
+        /// <item>aspect is negative or zero</item>
+        /// <item>zNear is negative or zero</item>
+        /// <item>zFar is negative or zero</item>
+        /// <item>zNear is larger than zFar</item>
+        /// </list>
+        /// </exception>
+        public static void CreatePerspectiveFieldOfView(float fovy, float aspect, float zNear, float zFar, out Matrix4 result)
+        {
+            if (fovy <= 0 || fovy > Math.PI)
+                throw new ArgumentOutOfRangeException("fovy");
+            if (aspect <= 0)
+                throw new ArgumentOutOfRangeException("aspect");
+            if (zNear <= 0)
+                throw new ArgumentOutOfRangeException("zNear");
+            if (zFar <= 0)
+                throw new ArgumentOutOfRangeException("zFar");
+            if (zNear >= zFar)
+                throw new ArgumentOutOfRangeException("zNear");
+            
+            float yMax = zNear * (float)System.Math.Tan(0.5f * fovy);
+            float yMin = -yMax;
+            float xMin = yMin * aspect;
+            float xMax = yMax * aspect;
+
+            CreatePerspectiveOffCenter(xMin, xMax, yMin, yMax, zNear, zFar, out result);
+        }
+        
+        /// <summary>
+        /// Creates a perspective projection matrix.
+        /// </summary>
+        /// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
+        /// <param name="aspect">Aspect ratio of the view (width / height)</param>
+        /// <param name="zNear">Distance to the near clip plane</param>
+        /// <param name="zFar">Distance to the far clip plane</param>
+        /// <returns>A projection matrix that transforms camera space to raster space</returns>
+        /// <exception cref="System.ArgumentOutOfRangeException">
+        /// Thrown under the following conditions:
+        /// <list type="bullet">
+        /// <item>fovy is zero, less than zero or larger than Math.PI</item>
+        /// <item>aspect is negative or zero</item>
+        /// <item>zNear is negative or zero</item>
+        /// <item>zFar is negative or zero</item>
+        /// <item>zNear is larger than zFar</item>
+        /// </list>
+        /// </exception>
+        public static Matrix4 CreatePerspectiveFieldOfView(float fovy, float aspect, float zNear, float zFar)
+        {
+            Matrix4 result;
+            CreatePerspectiveFieldOfView(fovy, aspect, zNear, zFar, out result);
+            return result;
+        }
+        
+        #endregion
+        
+        #region CreatePerspectiveOffCenter
+        
+        /// <summary>
+        /// Creates an perspective projection matrix.
+        /// </summary>
+        /// <param name="left">Left edge of the view frustum</param>
+        /// <param name="right">Right edge of the view frustum</param>
+        /// <param name="bottom">Bottom edge of the view frustum</param>
+        /// <param name="top">Top edge of the view frustum</param>
+        /// <param name="zNear">Distance to the near clip plane</param>
+        /// <param name="zFar">Distance to the far clip plane</param>
+        /// <param name="result">A projection matrix that transforms camera space to raster space</param>
+        /// <exception cref="System.ArgumentOutOfRangeException">
+        /// Thrown under the following conditions:
+        /// <list type="bullet">
+        /// <item>zNear is negative or zero</item>
+        /// <item>zFar is negative or zero</item>
+        /// <item>zNear is larger than zFar</item>
+        /// </list>
+        /// </exception>
+        public static void CreatePerspectiveOffCenter(float left, float right, float bottom, float top, float zNear, float zFar, out Matrix4 result)
+        {
+            if (zNear <= 0)
+                throw new ArgumentOutOfRangeException("zNear");
+            if (zFar <= 0)
+                throw new ArgumentOutOfRangeException("zFar");
+            if (zNear >= zFar)
+                throw new ArgumentOutOfRangeException("zNear");
+            
+            float x = (2.0f * zNear) / (right - left);
+            float y = (2.0f * zNear) / (top - bottom);
+            float a = (right + left) / (right - left);
+            float b = (top + bottom) / (top - bottom);
+            float c = -(zFar + zNear) / (zFar - zNear);
+            float d = -(2.0f * zFar * zNear) / (zFar - zNear);
+            
+            result = new Matrix4(x, 0, 0,  0,
+                                 0, y, 0,  0,
+                                 a, b, c, -1,
+                                 0, 0, d,  0);
+        }
+        
+        /// <summary>
+        /// Creates an perspective projection matrix.
+        /// </summary>
+        /// <param name="left">Left edge of the view frustum</param>
+        /// <param name="right">Right edge of the view frustum</param>
+        /// <param name="bottom">Bottom edge of the view frustum</param>
+        /// <param name="top">Top edge of the view frustum</param>
+        /// <param name="zNear">Distance to the near clip plane</param>
+        /// <param name="zFar">Distance to the far clip plane</param>
+        /// <returns>A projection matrix that transforms camera space to raster space</returns>
+        /// <exception cref="System.ArgumentOutOfRangeException">
+        /// Thrown under the following conditions:
+        /// <list type="bullet">
+        /// <item>zNear is negative or zero</item>
+        /// <item>zFar is negative or zero</item>
+        /// <item>zNear is larger than zFar</item>
+        /// </list>
+        /// </exception>
+        public static Matrix4 CreatePerspectiveOffCenter(float left, float right, float bottom, float top, float zNear, float zFar)
+        {
+            Matrix4 result;
+            CreatePerspectiveOffCenter(left, right, bottom, top, zNear, zFar, out result);
+            return result;
+        }
+        
+        #endregion
+
+        #region Obsolete Functions
+
+        #region Translation Functions
+
+        /// <summary>
+        /// Builds a translation matrix.
+        /// </summary>
+        /// <param name="trans">The translation vector.</param>
+        /// <returns>A new Matrix4 instance.</returns>
+        [Obsolete("Use CreateTranslation instead.")]
+        public static Matrix4 Translation(Vector3 trans)
+        {
+            return Translation(trans.X, trans.Y, trans.Z);
+        }
+
+        /// <summary>
+        /// Build a translation matrix with the given translation
+        /// </summary>
+        /// <param name="x">X translation</param>
+        /// <param name="y">Y translation</param>
+        /// <param name="z">Z translation</param>
+        /// <returns>A Translation matrix</returns>
+        [Obsolete("Use CreateTranslation instead.")]
+        public static Matrix4 Translation(float x, float y, float z)
+        {
+            Matrix4 result = Identity;
+            result.Row3 = new Vector4(x, y, z, 1.0f);
+            return result;
+        }
+
+        #endregion
+
+        #endregion
+
+        #region Scale Functions
+
+        /// <summary>
+        /// Build a scaling matrix
+        /// </summary>
+        /// <param name="scale">Single scale factor for x,y and z axes</param>
+        /// <returns>A scaling matrix</returns>
+        public static Matrix4 Scale(float scale)
+        {
+            return Scale(scale, scale, scale);
+        }
+
+        /// <summary>
+        /// Build a scaling matrix
+        /// </summary>
+        /// <param name="scale">Scale factors for x,y and z axes</param>
+        /// <returns>A scaling matrix</returns>
+        public static Matrix4 Scale(Vector3 scale)
+        {
+            return Scale(scale.X, scale.Y, scale.Z);
+        }
+
+        /// <summary>
+        /// Build a scaling matrix
+        /// </summary>
+        /// <param name="x">Scale factor for x-axis</param>
+        /// <param name="y">Scale factor for y-axis</param>
+        /// <param name="z">Scale factor for z-axis</param>
+        /// <returns>A scaling matrix</returns>
+        public static Matrix4 Scale(float x, float y, float z)
+        {
+            Matrix4 result;
+            result.Row0 = Vector4.UnitX * x;
+            result.Row1 = Vector4.UnitY * y;
+            result.Row2 = Vector4.UnitZ * z;
+            result.Row3 = Vector4.UnitW;
+            return result;
+        }
+
+        #endregion
+
+        #region Rotation Functions
+
+        /// <summary>
+        /// Build a rotation matrix that rotates about the x-axis
+        /// </summary>
+        /// <param name="angle">angle in radians to rotate counter-clockwise around the x-axis</param>
+        /// <returns>A rotation matrix</returns>
+        [Obsolete("Use CreateRotationX instead.")]
+        public static Matrix4 RotateX(float angle)
+        {
+            float cos = (float)System.Math.Cos(angle);
+            float sin = (float)System.Math.Sin(angle);
+
+            Matrix4 result;
+            result.Row0 = Vector4.UnitX;
+            result.Row1 = new Vector4(0.0f, cos, sin, 0.0f);
+            result.Row2 = new Vector4(0.0f, -sin, cos, 0.0f);
+            result.Row3 = Vector4.UnitW;
+            return result;
+        }
+
+        /// <summary>
+        /// Build a rotation matrix that rotates about the y-axis
+        /// </summary>
+        /// <param name="angle">angle in radians to rotate counter-clockwise around the y-axis</param>
+        /// <returns>A rotation matrix</returns>
+        [Obsolete("Use CreateRotationY instead.")]
+        public static Matrix4 RotateY(float angle)
+        {
+            float cos = (float)System.Math.Cos(angle);
+            float sin = (float)System.Math.Sin(angle);
+
+            Matrix4 result;
+            result.Row0 = new Vector4(cos, 0.0f, -sin, 0.0f);
+            result.Row1 = Vector4.UnitY;
+            result.Row2 = new Vector4(sin, 0.0f, cos, 0.0f);
+            result.Row3 = Vector4.UnitW;
+            return result;
+        }
+
+        /// <summary>
+        /// Build a rotation matrix that rotates about the z-axis
+        /// </summary>
+        /// <param name="angle">angle in radians to rotate counter-clockwise around the z-axis</param>
+        /// <returns>A rotation matrix</returns>
+        [Obsolete("Use CreateRotationZ instead.")]
+        public static Matrix4 RotateZ(float angle)
+        {
+            float cos = (float)System.Math.Cos(angle);
+            float sin = (float)System.Math.Sin(angle);
+
+            Matrix4 result;
+            result.Row0 = new Vector4(cos, sin, 0.0f, 0.0f);
+            result.Row1 = new Vector4(-sin, cos, 0.0f, 0.0f);
+            result.Row2 = Vector4.UnitZ;
+            result.Row3 = Vector4.UnitW;
+            return result;
+        }
+
+        /// <summary>
+        /// Build a rotation matrix to rotate about the given axis
+        /// </summary>
+        /// <param name="axis">the axis to rotate about</param>
+        /// <param name="angle">angle in radians to rotate counter-clockwise (looking in the direction of the given axis)</param>
+        /// <returns>A rotation matrix</returns>
+        [Obsolete("Use CreateFromAxisAngle instead.")]
+        public static Matrix4 Rotate(Vector3 axis, float angle)
+        {
+            float cos = (float)System.Math.Cos(-angle);
+            float sin = (float)System.Math.Sin(-angle);
+            float t = 1.0f - cos;
+
+            axis.Normalize();
+
+            Matrix4 result;
+            result.Row0 = new Vector4(t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0f);
+            result.Row1 = new Vector4(t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0f);
+            result.Row2 = new Vector4(t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0f);
+            result.Row3 = Vector4.UnitW;
+            return result;
+        }
+
+        /// <summary>
+        /// Build a rotation matrix from a quaternion
+        /// </summary>
+        /// <param name="q">the quaternion</param>
+        /// <returns>A rotation matrix</returns>
+        public static Matrix4 Rotate(Quaternion q)
+        {
+            Vector3 axis;
+            float angle;
+            q.ToAxisAngle(out axis, out angle);
+            return CreateFromAxisAngle(axis, angle);
+        }
+
+        #endregion
+
+        #region Camera Helper Functions
+
+        /// <summary>
+        /// Build a world space to camera space matrix
+        /// </summary>
+        /// <param name="eye">Eye (camera) position in world space</param>
+        /// <param name="target">Target position in world space</param>
+        /// <param name="up">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
+        /// <returns>A Matrix4 that transforms world space to camera space</returns>
+        public static Matrix4 LookAt(Vector3 eye, Vector3 target, Vector3 up)
+        {
+            Vector3 z = Vector3.Normalize(eye - target);
+            Vector3 x = Vector3.Normalize(Vector3.Cross(up, z));
+            Vector3 y = Vector3.Normalize(Vector3.Cross(z, x));
+
+            Matrix4 rot = new Matrix4(new Vector4(x.X, y.X, z.X, 0.0f),
+                                        new Vector4(x.Y, y.Y, z.Y, 0.0f),
+                                        new Vector4(x.Z, y.Z, z.Z, 0.0f),
+                                        Vector4.UnitW);
+
+            Matrix4 trans = Matrix4.CreateTranslation(-eye);
+
+            return trans * rot;
+        }
+
+        /// <summary>
+        /// Build a world space to camera space matrix
+        /// </summary>
+        /// <param name="eyeX">Eye (camera) position in world space</param>
+        /// <param name="eyeY">Eye (camera) position in world space</param>
+        /// <param name="eyeZ">Eye (camera) position in world space</param>
+        /// <param name="targetX">Target position in world space</param>
+        /// <param name="targetY">Target position in world space</param>
+        /// <param name="targetZ">Target position in world space</param>
+        /// <param name="upX">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
+        /// <param name="upY">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
+        /// <param name="upZ">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
+        /// <returns>A Matrix4 that transforms world space to camera space</returns>
+        public static Matrix4 LookAt(float eyeX, float eyeY, float eyeZ, float targetX, float targetY, float targetZ, float upX, float upY, float upZ)
+        {
+            return LookAt(new Vector3(eyeX, eyeY, eyeZ), new Vector3(targetX, targetY, targetZ), new Vector3(upX, upY, upZ));
+        }
+
+        /// <summary>
+        /// Build a projection matrix
+        /// </summary>
+        /// <param name="left">Left edge of the view frustum</param>
+        /// <param name="right">Right edge of the view frustum</param>
+        /// <param name="bottom">Bottom edge of the view frustum</param>
+        /// <param name="top">Top edge of the view frustum</param>
+        /// <param name="near">Distance to the near clip plane</param>
+        /// <param name="far">Distance to the far clip plane</param>
+        /// <returns>A projection matrix that transforms camera space to raster space</returns>
+        [Obsolete("Use CreatePerspectiveOffCenter instead.")]
+        public static Matrix4 Frustum(float left, float right, float bottom, float top, float near, float far)
+        {
+            float invRL = 1.0f / (right - left);
+            float invTB = 1.0f / (top - bottom);
+            float invFN = 1.0f / (far - near);
+            return new Matrix4(new Vector4(2.0f * near * invRL, 0.0f, 0.0f, 0.0f),
+                               new Vector4(0.0f, 2.0f * near * invTB, 0.0f, 0.0f),
+                               new Vector4((right + left) * invRL, (top + bottom) * invTB, -(far + near) * invFN, -1.0f),
+                               new Vector4(0.0f, 0.0f, -2.0f * far * near * invFN, 0.0f));
+        }
+
+        /// <summary>
+        /// Build a projection matrix
+        /// </summary>
+        /// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
+        /// <param name="aspect">Aspect ratio of the view (width / height)</param>
+        /// <param name="near">Distance to the near clip plane</param>
+        /// <param name="far">Distance to the far clip plane</param>
+        /// <returns>A projection matrix that transforms camera space to raster space</returns>
+        [Obsolete("Use CreatePerspectiveFieldOfView instead.")]
+        public static Matrix4 Perspective(float fovy, float aspect, float near, float far)
+        {
+            float yMax = near * (float)System.Math.Tan(0.5f * fovy);
+            float yMin = -yMax;
+            float xMin = yMin * aspect;
+            float xMax = yMax * aspect;
+
+            return Frustum(xMin, xMax, yMin, yMax, near, far);
+        }
+
+        #endregion
+
+        #region Multiply Functions
+
+        /// <summary>
+        /// Multiplies two instances.
+        /// </summary>
+        /// <param name="left">The left operand of the multiplication.</param>
+        /// <param name="right">The right operand of the multiplication.</param>
+        /// <returns>A new instance that is the result of the multiplication</returns>
+        public static Matrix4 Mult(Matrix4 left, Matrix4 right)
+        {
+            Matrix4 result;
+            Mult(ref left, ref right, out result);
+            return result;
+        }
+
+        /// <summary>
+        /// Multiplies two instances.
+        /// </summary>
+        /// <param name="left">The left operand of the multiplication.</param>
+        /// <param name="right">The right operand of the multiplication.</param>
+        /// <param name="result">A new instance that is the result of the multiplication</param>
+        public static void Mult(ref Matrix4 left, ref Matrix4 right, out Matrix4 result)
+        {
+            result = new Matrix4(
+                left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31 + left.M14 * right.M41,
+                left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32 + left.M14 * right.M42,
+                left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33 + left.M14 * right.M43,
+                left.M11 * right.M14 + left.M12 * right.M24 + left.M13 * right.M34 + left.M14 * right.M44,
+                left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31 + left.M24 * right.M41,
+                left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32 + left.M24 * right.M42,
+                left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33 + left.M24 * right.M43,
+                left.M21 * right.M14 + left.M22 * right.M24 + left.M23 * right.M34 + left.M24 * right.M44,
+                left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31 + left.M34 * right.M41,
+                left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32 + left.M34 * right.M42,
+                left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33 + left.M34 * right.M43,
+                left.M31 * right.M14 + left.M32 * right.M24 + left.M33 * right.M34 + left.M34 * right.M44,
+                left.M41 * right.M11 + left.M42 * right.M21 + left.M43 * right.M31 + left.M44 * right.M41,
+                left.M41 * right.M12 + left.M42 * right.M22 + left.M43 * right.M32 + left.M44 * right.M42,
+                left.M41 * right.M13 + left.M42 * right.M23 + left.M43 * right.M33 + left.M44 * right.M43,
+                left.M41 * right.M14 + left.M42 * right.M24 + left.M43 * right.M34 + left.M44 * right.M44);
+        }
+
+        #endregion
+
+        #region Invert Functions
+
+        /// <summary>
+        /// Calculate the inverse of the given matrix
+        /// </summary>
+        /// <param name="mat">The matrix to invert</param>
+        /// <returns>The inverse of the given matrix if it has one, or the input if it is singular</returns>
+        /// <exception cref="InvalidOperationException">Thrown if the Matrix4 is singular.</exception>
+        public static Matrix4 Invert(Matrix4 mat)
+        {
+            int[] colIdx = { 0, 0, 0, 0 };
+            int[] rowIdx = { 0, 0, 0, 0 };
+            int[] pivotIdx = { -1, -1, -1, -1 };
+
+            // convert the matrix to an array for easy looping
+            float[,] inverse = {{mat.Row0.X, mat.Row0.Y, mat.Row0.Z, mat.Row0.W}, 
+                                {mat.Row1.X, mat.Row1.Y, mat.Row1.Z, mat.Row1.W}, 
+                                {mat.Row2.X, mat.Row2.Y, mat.Row2.Z, mat.Row2.W}, 
+                                {mat.Row3.X, mat.Row3.Y, mat.Row3.Z, mat.Row3.W} };
+            int icol = 0;
+            int irow = 0;
+            for (int i = 0; i < 4; i++)
+            {
+                // Find the largest pivot value
+                float maxPivot = 0.0f;
+                for (int j = 0; j < 4; j++)
+                {
+                    if (pivotIdx[j] != 0)
+                    {
+                        for (int k = 0; k < 4; ++k)
+                        {
+                            if (pivotIdx[k] == -1)
+                            {
+                                float absVal = System.Math.Abs(inverse[j, k]);
+                                if (absVal > maxPivot)
+                                {
+                                    maxPivot = absVal;
+                                    irow = j;
+                                    icol = k;
+                                }
+                            }
+                            else if (pivotIdx[k] > 0)
+                            {
+                                return mat;
+                            }
+                        }
+                    }
+                }
+
+                ++(pivotIdx[icol]);
+
+                // Swap rows over so pivot is on diagonal
+                if (irow != icol)
+                {
+                    for (int k = 0; k < 4; ++k)
+                    {
+                        float f = inverse[irow, k];
+                        inverse[irow, k] = inverse[icol, k];
+                        inverse[icol, k] = f;
+                    }
+                }
+
+                rowIdx[i] = irow;
+                colIdx[i] = icol;
+
+                float pivot = inverse[icol, icol];
+                // check for singular matrix
+                if (pivot == 0.0f)
+                {
+                    throw new InvalidOperationException("Matrix is singular and cannot be inverted.");
+                    //return mat;
+                }
+
+                // Scale row so it has a unit diagonal
+                float oneOverPivot = 1.0f / pivot;
+                inverse[icol, icol] = 1.0f;
+                for (int k = 0; k < 4; ++k)
+                    inverse[icol, k] *= oneOverPivot;
+
+                // Do elimination of non-diagonal elements
+                for (int j = 0; j < 4; ++j)
+                {
+                    // check this isn't on the diagonal
+                    if (icol != j)
+                    {
+                        float f = inverse[j, icol];
+                        inverse[j, icol] = 0.0f;
+                        for (int k = 0; k < 4; ++k)
+                            inverse[j, k] -= inverse[icol, k] * f;
+                    }
+                }
+            }
+
+            for (int j = 3; j >= 0; --j)
+            {
+                int ir = rowIdx[j];
+                int ic = colIdx[j];
+                for (int k = 0; k < 4; ++k)
+                {
+                    float f = inverse[k, ir];
+                    inverse[k, ir] = inverse[k, ic];
+                    inverse[k, ic] = f;
+                }
+            }
+
+            mat.Row0 = new Vector4(inverse[0, 0], inverse[0, 1], inverse[0, 2], inverse[0, 3]);
+            mat.Row1 = new Vector4(inverse[1, 0], inverse[1, 1], inverse[1, 2], inverse[1, 3]);
+            mat.Row2 = new Vector4(inverse[2, 0], inverse[2, 1], inverse[2, 2], inverse[2, 3]);
+            mat.Row3 = new Vector4(inverse[3, 0], inverse[3, 1], inverse[3, 2], inverse[3, 3]);
+            return mat;
+        }
+
+        #endregion
+
+        #region Transpose
+
+        /// <summary>
+        /// Calculate the transpose of the given matrix
+        /// </summary>
+        /// <param name="mat">The matrix to transpose</param>
+        /// <returns>The transpose of the given matrix</returns>
+        public static Matrix4 Transpose(Matrix4 mat)
+        {
+            return new Matrix4(mat.Column0, mat.Column1, mat.Column2, mat.Column3);
+        }
+
+
+        /// <summary>
+        /// Calculate the transpose of the given matrix
+        /// </summary>
+        /// <param name="mat">The matrix to transpose</param>
+        /// <param name="result">The result of the calculation</param>
+        public static void Transpose(ref Matrix4 mat, out Matrix4 result)
+        {
+            result.Row0 = mat.Column0;
+            result.Row1 = mat.Column1;
+            result.Row2 = mat.Column2;
+            result.Row3 = mat.Column3;
+        }
+
+        #endregion
+
+        #endregion
+
+        #region Operators
+
+        /// <summary>
+        /// Matrix multiplication
+        /// </summary>
+        /// <param name="left">left-hand operand</param>
+        /// <param name="right">right-hand operand</param>
+        /// <returns>A new Matrix44 which holds the result of the multiplication</returns>
+        public static Matrix4 operator *(Matrix4 left, Matrix4 right)
+        {
+            return Matrix4.Mult(left, right);
+        }
+
+        /// <summary>
+        /// Compares two instances for equality.
+        /// </summary>
+        /// <param name="left">The first instance.</param>
+        /// <param name="right">The second instance.</param>
+        /// <returns>True, if left equals right; false otherwise.</returns>
+        public static bool operator ==(Matrix4 left, Matrix4 right)
+        {
+            return left.Equals(right);
+        }
+
+        /// <summary>
+        /// Compares two instances for inequality.
+        /// </summary>
+        /// <param name="left">The first instance.</param>
+        /// <param name="right">The second instance.</param>
+        /// <returns>True, if left does not equal right; false otherwise.</returns>
+        public static bool operator !=(Matrix4 left, Matrix4 right)
+        {
+            return !left.Equals(right);
+        }
+
+        #endregion
+
+        #region Overrides
+
+        #region public override string ToString()
+
+        /// <summary>
+        /// Returns a System.String that represents the current Matrix44.
+        /// </summary>
+        /// <returns></returns>
+        public override string ToString()
+        {
+            return String.Format("{0}\n{1}\n{2}\n{3}", Row0, Row1, Row2, Row3);
+        }
+
+        #endregion
+
+        #region public override int GetHashCode()
+
+        /// <summary>
+        /// Returns the hashcode for this instance.
+        /// </summary>
+        /// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
+        public override int GetHashCode()
+        {
+            return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode() ^ Row3.GetHashCode();
+        }
+
+        #endregion
+
+        #region public override bool Equals(object obj)
+
+        /// <summary>
+        /// Indicates whether this instance and a specified object are equal.
+        /// </summary>
+        /// <param name="obj">The object to compare tresult.</param>
+        /// <returns>True if the instances are equal; false otherwise.</returns>
+        public override bool Equals(object obj)
+        {
+            if (!(obj is Matrix4))
+                return false;
+
+            return this.Equals((Matrix4)obj);
+        }
+
+        #endregion
+
+        #endregion
+
+        #endregion
+
+        #region IEquatable<Matrix4> Members
+
+        /// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
+        /// <param name="other">An matrix to compare with this matrix.</param>
+        /// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
+        public bool Equals(Matrix4 other)
+        {
+            return
+                Row0 == other.Row0 &&
+                Row1 == other.Row1 &&
+                Row2 == other.Row2 &&
+                Row3 == other.Row3;
+        }
+
+        #endregion
+    }
 }

+ 34 - 34
Script/AtomicNET/AtomicNET/Math/Plane.cs

@@ -3,42 +3,42 @@ using System.Runtime.InteropServices;
 
 namespace AtomicEngine
 {
-	[StructLayout(LayoutKind.Sequential)]
-	public struct Plane
-	{
-		/// <summary>
-		/// Plane normal.
-		/// </summary>
-		public Vector3 Normal;
+    [StructLayout(LayoutKind.Sequential)]
+    public struct Plane
+    {
+        /// <summary>
+        /// Plane normal.
+        /// </summary>
+        public Vector3 Normal;
 
-		/// <summary>
-		/// Plane absolute normal.
-		/// </summary>
-		public Vector3 AbsNormal;
+        /// <summary>
+        /// Plane absolute normal.
+        /// </summary>
+        public Vector3 AbsNormal;
 
-		/// <summary>
-		/// Plane constant.
-		/// </summary>
-		public float D;
+        /// <summary>
+        /// Plane constant.
+        /// </summary>
+        public float D;
 
-		/// <summary>
-		/// Construct from a normal vector and a point on the plane.
-		/// </summary>
-		public Plane(Vector3 normal, Vector3 point)
-		{
-			Normal = Vector3.Normalize(normal);
-			AbsNormal = new Vector3(Math.Abs(Normal.X), Math.Abs(Normal.Y), Math.Abs(Normal.Z));
-			D = - Vector3.Dot(Normal, point);
-		}
+        /// <summary>
+        /// Construct from a normal vector and a point on the plane.
+        /// </summary>
+        public Plane(Vector3 normal, Vector3 point)
+        {
+            Normal = Vector3.Normalize(normal);
+            AbsNormal = new Vector3(Math.Abs(Normal.X), Math.Abs(Normal.Y), Math.Abs(Normal.Z));
+            D = - Vector3.Dot(Normal, point);
+        }
 
-		/// <summary>
-		/// Construct from a 4-dimensional vector, where the w coordinate is the plane parameter.
-		/// </summary>
-		public Plane(Vector4 plane)
-		{
-			Normal = new Vector3(plane.X, plane.Y, plane.Z);
-			AbsNormal = new Vector3(Math.Abs(plane.X), Math.Abs(plane.Y), Math.Abs(plane.Z));
-			D = plane.W;
-		}
-	}
+        /// <summary>
+        /// Construct from a 4-dimensional vector, where the w coordinate is the plane parameter.
+        /// </summary>
+        public Plane(Vector4 plane)
+        {
+            Normal = new Vector3(plane.X, plane.Y, plane.Z);
+            AbsNormal = new Vector3(Math.Abs(plane.X), Math.Abs(plane.Y), Math.Abs(plane.Z));
+            D = plane.W;
+        }
+    }
 }

+ 1024 - 1024
Script/AtomicNET/AtomicNET/Math/Vector2.cs

@@ -26,1030 +26,1030 @@ using System;
 using System.Runtime.InteropServices;
 namespace AtomicEngine
 {
-	/// <summary>Represents a 2D vector using two single-precision floating-point numbers.</summary>
-	/// <remarks>
-	/// The Vector2 structure is suitable for interoperation with unmanaged code requiring two consecutive floats.
-	/// </remarks>
-	[StructLayout(LayoutKind.Sequential)]
-	public struct Vector2 : IEquatable<Vector2>
-	{
-		#region Fields
-
-		/// <summary>
-		/// The X component of the Vector2.
-		/// </summary>
-		public float X;
-
-		/// <summary>
-		/// The Y component of the Vector2.
-		/// </summary>
-		public float Y;
-
-		#endregion
-
-		#region Constructors
-
-		/// <summary>
-		/// Constructs a new Vector2.
-		/// </summary>
-		/// <param name="x">The x coordinate of the net Vector2.</param>
-		/// <param name="y">The y coordinate of the net Vector2.</param>
-		public Vector2(float x, float y)
-		{
-			X = x;
-			Y = y;
-		}
-
-		/// <summary>
-		/// Constructs a new Vector2 from the given Vector2.
-		/// </summary>
-		/// <param name="v">The Vector2 to copy components from.</param>
-		[Obsolete]
-		public Vector2(Vector2 v)
-		{
-			X = v.X;
-			Y = v.Y;
-		}
-
-		/// <summary>
-		/// Constructs a new Vector2 from the given Vector3.
-		/// </summary>
-		/// <param name="v">The Vector3 to copy components from. Z is discarded.</param>
-		[Obsolete]
-		public Vector2(Vector3 v)
-		{
-			X = v.X;
-			Y = v.Y;
-		}
-
-		/// <summary>
-		/// Constructs a new Vector2 from the given Vector4.
-		/// </summary>
-		/// <param name="v">The Vector4 to copy components from. Z and W are discarded.</param>
-		[Obsolete]
-		public Vector2(Vector4 v)
-		{
-			X = v.X;
-			Y = v.Y;
-		}
-
-		#endregion
-
-		#region Public Members
-
-		#region Instance
-
-		#region public void Add()
-
-		/// <summary>Add the Vector passed as parameter to this instance.</summary>
-		/// <param name="right">Right operand. This parameter is only read from.</param>
-		[Obsolete("Use static Add() method instead.")]
-		public void Add(Vector2 right)
-		{
-			this.X += right.X;
-			this.Y += right.Y;
-		}
-
-		/// <summary>Add the Vector passed as parameter to this instance.</summary>
-		/// <param name="right">Right operand. This parameter is only read from.</param>
-		[CLSCompliant(false)]
-		[Obsolete("Use static Add() method instead.")]
-		public void Add(ref Vector2 right)
-		{
-			this.X += right.X;
-			this.Y += right.Y;
-		}
-
-		#endregion public void Add()
-
-		#region public void Sub()
-
-		/// <summary>Subtract the Vector passed as parameter from this instance.</summary>
-		/// <param name="right">Right operand. This parameter is only read from.</param>
-		[Obsolete("Use static Subtract() method instead.")]
-		public void Sub(Vector2 right)
-		{
-			this.X -= right.X;
-			this.Y -= right.Y;
-		}
-
-		/// <summary>Subtract the Vector passed as parameter from this instance.</summary>
-		/// <param name="right">Right operand. This parameter is only read from.</param>
-		[CLSCompliant(false)]
-		[Obsolete("Use static Subtract() method instead.")]
-		public void Sub(ref Vector2 right)
-		{
-			this.X -= right.X;
-			this.Y -= right.Y;
-		}
-
-		#endregion public void Sub()
-
-		#region public void Mult()
-
-		/// <summary>Multiply this instance by a scalar.</summary>
-		/// <param name="f">Scalar operand.</param>
-		[Obsolete("Use static Multiply() method instead.")]
-		public void Mult(float f)
-		{
-			this.X *= f;
-			this.Y *= f;
-		}
-
-		#endregion public void Mult()
-
-		#region public void Div()
-
-		/// <summary>Divide this instance by a scalar.</summary>
-		/// <param name="f">Scalar operand.</param>
-		[Obsolete("Use static Divide() method instead.")]
-		public void Div(float f)
-		{
-			float mult = 1.0f / f;
-			this.X *= mult;
-			this.Y *= mult;
-		}
-
-		#endregion public void Div()
-
-		#region public float Length
-
-		/// <summary>
-		/// Gets the length (magnitude) of the vector.
-		/// </summary>
-		/// <see cref="LengthFast"/>
-		/// <seealso cref="LengthSquared"/>
-		public float Length
-		{
-			get
-			{
-				return (float)System.Math.Sqrt(X * X + Y * Y);
-			}
-		}
-
-		#endregion
-
-		#region public float LengthFast
-
-		/// <summary>
-		/// Gets an approximation of the vector length (magnitude).
-		/// </summary>
-		/// <remarks>
-		/// This property uses an approximation of the square root function to calculate vector magnitude, with
-		/// an upper error bound of 0.001.
-		/// </remarks>
-		/// <see cref="Length"/>
-		/// <seealso cref="LengthSquared"/>
-		public float LengthFast
-		{
-			get
-			{
-				return 1.0f / MathHelper.InverseSqrtFast(X * X + Y * Y);
-			}
-		}
-
-		#endregion
-
-		#region public float LengthSquared
-
-		/// <summary>
-		/// Gets the square of the vector length (magnitude).
-		/// </summary>
-		/// <remarks>
-		/// This property avoids the costly square root operation required by the Length property. This makes it more suitable
-		/// for comparisons.
-		/// </remarks>
-		/// <see cref="Length"/>
-		/// <seealso cref="LengthFast"/>
-		public float LengthSquared
-		{
-			get
-			{
-				return X * X + Y * Y;
-			}
-		}
-
-		#endregion
-
-		#region public Vector2 PerpendicularRight
-
-		/// <summary>
-		/// Gets the perpendicular vector on the right side of this vector.
-		/// </summary>
-		public Vector2 PerpendicularRight
-		{
-			get
-			{
-				return new Vector2(Y, -X);
-			}
-		}
-
-		#endregion
-
-		#region public Vector2 PerpendicularLeft
-
-		/// <summary>
-		/// Gets the perpendicular vector on the left side of this vector.
-		/// </summary>
-		public Vector2 PerpendicularLeft
-		{
-			get
-			{
-				return new Vector2(-Y, X);
-			}
-		}
-
-		#endregion
-
-		#region public void Normalize()
-
-		/// <summary>
-		/// Scales the Vector2 to unit length.
-		/// </summary>
-		public void Normalize()
-		{
-			float scale = 1.0f / this.Length;
-			X *= scale;
-			Y *= scale;
-		}
-
-		#endregion
-
-		#region public void NormalizeFast()
-
-		/// <summary>
-		/// Scales the Vector2 to approximately unit length.
-		/// </summary>
-		public void NormalizeFast()
-		{
-			float scale = MathHelper.InverseSqrtFast(X * X + Y * Y);
-			X *= scale;
-			Y *= scale;
-		}
-
-		#endregion
-
-		#region public void Scale()
-
-		/// <summary>
-		/// Scales the current Vector2 by the given amounts.
-		/// </summary>
-		/// <param name="sx">The scale of the X component.</param>
-		/// <param name="sy">The scale of the Y component.</param>
-		[Obsolete("Use static Multiply() method instead.")]
-		public void Scale(float sx, float sy)
-		{
-			this.X = X * sx;
-			this.Y = Y * sy;
-		}
-
-		/// <summary>Scales this instance by the given parameter.</summary>
-		/// <param name="scale">The scaling of the individual components.</param>
-		[Obsolete("Use static Multiply() method instead.")]
-		public void Scale(Vector2 scale)
-		{
-			this.X *= scale.X;
-			this.Y *= scale.Y;
-		}
-
-		/// <summary>Scales this instance by the given parameter.</summary>
-		/// <param name="scale">The scaling of the individual components.</param>
-		[CLSCompliant(false)]
-		[Obsolete("Use static Multiply() method instead.")]
-		public void Scale(ref Vector2 scale)
-		{
-			this.X *= scale.X;
-			this.Y *= scale.Y;
-		}
-
-		#endregion public void Scale()
-
-		#endregion
-
-		#region Static
-
-		#region Fields
-
-		/// <summary>
-		/// Defines a unit-length Vector2 that points towards the X-axis.
-		/// </summary>
-		public static readonly Vector2 UnitX = new Vector2(1, 0);
-
-		/// <summary>
-		/// Defines a unit-length Vector2 that points towards the Y-axis.
-		/// </summary>
-		public static readonly Vector2 UnitY = new Vector2(0, 1);
-
-		/// <summary>
-		/// Defines a zero-length Vector2.
-		/// </summary>
-		public static readonly Vector2 Zero = new Vector2(0, 0);
-
-		/// <summary>
-		/// Defines an instance with all components set to 1.
-		/// </summary>
-		public static readonly Vector2 One = new Vector2(1, 1);
-
-		/// <summary>
-		/// Defines the size of the Vector2 struct in bytes.
-		/// </summary>
-		public static readonly int SizeInBytes = Marshal.SizeOf(new Vector2());
-
-		#endregion
-
-		#region Obsolete
-
-		#region Sub
-
-		/// <summary>
-		/// Subtract one Vector from another
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <returns>Result of subtraction</returns>
-		[Obsolete("Use static Subtract() method instead.")]
-		public static Vector2 Sub(Vector2 a, Vector2 b)
-		{
-			a.X -= b.X;
-			a.Y -= b.Y;
-			return a;
-		}
-
-		/// <summary>
-		/// Subtract one Vector from another
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <param name="result">Result of subtraction</param>
-		[Obsolete("Use static Subtract() method instead.")]
-		public static void Sub(ref Vector2 a, ref Vector2 b, out Vector2 result)
-		{
-			result.X = a.X - b.X;
-			result.Y = a.Y - b.Y;
-		}
-
-		#endregion
-
-		#region Mult
-
-		/// <summary>
-		/// Multiply a vector and a scalar
-		/// </summary>
-		/// <param name="a">Vector operand</param>
-		/// <param name="f">Scalar operand</param>
-		/// <returns>Result of the multiplication</returns>
-		[Obsolete("Use static Multiply() method instead.")]
-		public static Vector2 Mult(Vector2 a, float f)
-		{
-			a.X *= f;
-			a.Y *= f;
-			return a;
-		}
-
-		/// <summary>
-		/// Multiply a vector and a scalar
-		/// </summary>
-		/// <param name="a">Vector operand</param>
-		/// <param name="f">Scalar operand</param>
-		/// <param name="result">Result of the multiplication</param>
-		[Obsolete("Use static Multiply() method instead.")]
-		public static void Mult(ref Vector2 a, float f, out Vector2 result)
-		{
-			result.X = a.X * f;
-			result.Y = a.Y * f;
-		}
-
-		#endregion
-
-		#region Div
-
-		/// <summary>
-		/// Divide a vector by a scalar
-		/// </summary>
-		/// <param name="a">Vector operand</param>
-		/// <param name="f">Scalar operand</param>
-		/// <returns>Result of the division</returns>
-		[Obsolete("Use static Divide() method instead.")]
-		public static Vector2 Div(Vector2 a, float f)
-		{
-			float mult = 1.0f / f;
-			a.X *= mult;
-			a.Y *= mult;
-			return a;
-		}
-
-		/// <summary>
-		/// Divide a vector by a scalar
-		/// </summary>
-		/// <param name="a">Vector operand</param>
-		/// <param name="f">Scalar operand</param>
-		/// <param name="result">Result of the division</param>
-		[Obsolete("Use static Divide() method instead.")]
-		public static void Div(ref Vector2 a, float f, out Vector2 result)
-		{
-			float mult = 1.0f / f;
-			result.X = a.X * mult;
-			result.Y = a.Y * mult;
-		}
-
-		#endregion
-
-		#endregion
-
-		#region Add
-
-		/// <summary>
-		/// Adds two vectors.
-		/// </summary>
-		/// <param name="a">Left operand.</param>
-		/// <param name="b">Right operand.</param>
-		/// <returns>Result of operation.</returns>
-		public static Vector2 Add(Vector2 a, Vector2 b)
-		{
-			Add(ref a, ref b, out a);
-			return a;
-		}
-
-		/// <summary>
-		/// Adds two vectors.
-		/// </summary>
-		/// <param name="a">Left operand.</param>
-		/// <param name="b">Right operand.</param>
-		/// <param name="result">Result of operation.</param>
-		public static void Add(ref Vector2 a, ref Vector2 b, out Vector2 result)
-		{
-			result = new Vector2(a.X + b.X, a.Y + b.Y);
-		}
-
-		#endregion
-
-		#region Subtract
-
-		/// <summary>
-		/// Subtract one Vector from another
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <returns>Result of subtraction</returns>
-		public static Vector2 Subtract(Vector2 a, Vector2 b)
-		{
-			Subtract(ref a, ref b, out a);
-			return a;
-		}
-
-		/// <summary>
-		/// Subtract one Vector from another
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <param name="result">Result of subtraction</param>
-		public static void Subtract(ref Vector2 a, ref Vector2 b, out Vector2 result)
-		{
-			result = new Vector2(a.X - b.X, a.Y - b.Y);
-		}
-
-		#endregion
-
-		#region Multiply
-
-		/// <summary>
-		/// Multiplies a vector by a scalar.
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of the operation.</returns>
-		public static Vector2 Multiply(Vector2 vector, float scale)
-		{
-			Multiply(ref vector, scale, out vector);
-			return vector;
-		}
-
-		/// <summary>
-		/// Multiplies a vector by a scalar.
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <param name="result">Result of the operation.</param>
-		public static void Multiply(ref Vector2 vector, float scale, out Vector2 result)
-		{
-			result = new Vector2(vector.X * scale, vector.Y * scale);
-		}
-
-		/// <summary>
-		/// Multiplies a vector by the components a vector (scale).
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of the operation.</returns>
-		public static Vector2 Multiply(Vector2 vector, Vector2 scale)
-		{
-			Multiply(ref vector, ref scale, out vector);
-			return vector;
-		}
-
-		/// <summary>
-		/// Multiplies a vector by the components of a vector (scale).
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <param name="result">Result of the operation.</param>
-		public static void Multiply(ref Vector2 vector, ref Vector2 scale, out Vector2 result)
-		{
-			result = new Vector2(vector.X * scale.X, vector.Y * scale.Y);
-		}
-
-		#endregion
-
-		#region Divide
-
-		/// <summary>
-		/// Divides a vector by a scalar.
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of the operation.</returns>
-		public static Vector2 Divide(Vector2 vector, float scale)
-		{
-			Divide(ref vector, scale, out vector);
-			return vector;
-		}
-
-		/// <summary>
-		/// Divides a vector by a scalar.
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <param name="result">Result of the operation.</param>
-		public static void Divide(ref Vector2 vector, float scale, out Vector2 result)
-		{
-			Multiply(ref vector, 1 / scale, out result);
-		}
-
-		/// <summary>
-		/// Divides a vector by the components of a vector (scale).
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of the operation.</returns>
-		public static Vector2 Divide(Vector2 vector, Vector2 scale)
-		{
-			Divide(ref vector, ref scale, out vector);
-			return vector;
-		}
-
-		/// <summary>
-		/// Divide a vector by the components of a vector (scale).
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <param name="result">Result of the operation.</param>
-		public static void Divide(ref Vector2 vector, ref Vector2 scale, out Vector2 result)
-		{
-			result = new Vector2(vector.X / scale.X, vector.Y / scale.Y);
-		}
-
-		#endregion
-
-		#region ComponentMin
-
-		/// <summary>
-		/// Calculate the component-wise minimum of two vectors
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <returns>The component-wise minimum</returns>
-		public static Vector2 ComponentMin(Vector2 a, Vector2 b)
-		{
-			a.X = a.X < b.X ? a.X : b.X;
-			a.Y = a.Y < b.Y ? a.Y : b.Y;
-			return a;
-		}
-
-		/// <summary>
-		/// Calculate the component-wise minimum of two vectors
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <param name="result">The component-wise minimum</param>
-		public static void ComponentMin(ref Vector2 a, ref Vector2 b, out Vector2 result)
-		{
-			result.X = a.X < b.X ? a.X : b.X;
-			result.Y = a.Y < b.Y ? a.Y : b.Y;
-		}
-
-		#endregion
-
-		#region ComponentMax
-
-		/// <summary>
-		/// Calculate the component-wise maximum of two vectors
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <returns>The component-wise maximum</returns>
-		public static Vector2 ComponentMax(Vector2 a, Vector2 b)
-		{
-			a.X = a.X > b.X ? a.X : b.X;
-			a.Y = a.Y > b.Y ? a.Y : b.Y;
-			return a;
-		}
-
-		/// <summary>
-		/// Calculate the component-wise maximum of two vectors
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <param name="result">The component-wise maximum</param>
-		public static void ComponentMax(ref Vector2 a, ref Vector2 b, out Vector2 result)
-		{
-			result.X = a.X > b.X ? a.X : b.X;
-			result.Y = a.Y > b.Y ? a.Y : b.Y;
-		}
-
-		#endregion
-
-		#region Min
-
-		/// <summary>
-		/// Returns the Vector3 with the minimum magnitude
-		/// </summary>
-		/// <param name="left">Left operand</param>
-		/// <param name="right">Right operand</param>
-		/// <returns>The minimum Vector3</returns>
-		public static Vector2 Min(Vector2 left, Vector2 right)
-		{
-			return left.LengthSquared < right.LengthSquared ? left : right;
-		}
-
-		#endregion
-
-		#region Max
-
-		/// <summary>
-		/// Returns the Vector3 with the minimum magnitude
-		/// </summary>
-		/// <param name="left">Left operand</param>
-		/// <param name="right">Right operand</param>
-		/// <returns>The minimum Vector3</returns>
-		public static Vector2 Max(Vector2 left, Vector2 right)
-		{
-			return left.LengthSquared >= right.LengthSquared ? left : right;
-		}
-
-		#endregion
-
-		#region Clamp
-
-		/// <summary>
-		/// Clamp a vector to the given minimum and maximum vectors
-		/// </summary>
-		/// <param name="vec">Input vector</param>
-		/// <param name="min">Minimum vector</param>
-		/// <param name="max">Maximum vector</param>
-		/// <returns>The clamped vector</returns>
-		public static Vector2 Clamp(Vector2 vec, Vector2 min, Vector2 max)
-		{
-			vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
-			vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
-			return vec;
-		}
-
-		/// <summary>
-		/// Clamp a vector to the given minimum and maximum vectors
-		/// </summary>
-		/// <param name="vec">Input vector</param>
-		/// <param name="min">Minimum vector</param>
-		/// <param name="max">Maximum vector</param>
-		/// <param name="result">The clamped vector</param>
-		public static void Clamp(ref Vector2 vec, ref Vector2 min, ref Vector2 max, out Vector2 result)
-		{
-			result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
-			result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
-		}
-
-		#endregion
-
-		#region Normalize
-
-		/// <summary>
-		/// Scale a vector to unit length
-		/// </summary>
-		/// <param name="vec">The input vector</param>
-		/// <returns>The normalized vector</returns>
-		public static Vector2 Normalize(Vector2 vec)
-		{
-			float scale = 1.0f / vec.Length;
-			vec.X *= scale;
-			vec.Y *= scale;
-			return vec;
-		}
-
-		/// <summary>
-		/// Scale a vector to unit length
-		/// </summary>
-		/// <param name="vec">The input vector</param>
-		/// <param name="result">The normalized vector</param>
-		public static void Normalize(ref Vector2 vec, out Vector2 result)
-		{
-			float scale = 1.0f / vec.Length;
-			result.X = vec.X * scale;
-			result.Y = vec.Y * scale;
-		}
-
-		#endregion
-
-		#region NormalizeFast
-
-		/// <summary>
-		/// Scale a vector to approximately unit length
-		/// </summary>
-		/// <param name="vec">The input vector</param>
-		/// <returns>The normalized vector</returns>
-		public static Vector2 NormalizeFast(Vector2 vec)
-		{
-			float scale = MathHelper.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
-			vec.X *= scale;
-			vec.Y *= scale;
-			return vec;
-		}
-
-		/// <summary>
-		/// Scale a vector to approximately unit length
-		/// </summary>
-		/// <param name="vec">The input vector</param>
-		/// <param name="result">The normalized vector</param>
-		public static void NormalizeFast(ref Vector2 vec, out Vector2 result)
-		{
-			float scale = MathHelper.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
-			result.X = vec.X * scale;
-			result.Y = vec.Y * scale;
-		}
-
-		#endregion
-
-		#region Dot
-
-		/// <summary>
-		/// Calculate the dot (scalar) product of two vectors
-		/// </summary>
-		/// <param name="left">First operand</param>
-		/// <param name="right">Second operand</param>
-		/// <returns>The dot product of the two inputs</returns>
-		public static float Dot(Vector2 left, Vector2 right)
-		{
-			return left.X * right.X + left.Y * right.Y;
-		}
-
-		/// <summary>
-		/// Calculate the dot (scalar) product of two vectors
-		/// </summary>
-		/// <param name="left">First operand</param>
-		/// <param name="right">Second operand</param>
-		/// <param name="result">The dot product of the two inputs</param>
-		public static void Dot(ref Vector2 left, ref Vector2 right, out float result)
-		{
-			result = left.X * right.X + left.Y * right.Y;
-		}
-
-		#endregion
-
-		#region Lerp
-
-		/// <summary>
-		/// Returns a new Vector that is the linear blend of the 2 given Vectors
-		/// </summary>
-		/// <param name="a">First input vector</param>
-		/// <param name="b">Second input vector</param>
-		/// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
-		/// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
-		public static Vector2 Lerp(Vector2 a, Vector2 b, float blend)
-		{
-			a.X = blend * (b.X - a.X) + a.X;
-			a.Y = blend * (b.Y - a.Y) + a.Y;
-			return a;
-		}
-
-		/// <summary>
-		/// Returns a new Vector that is the linear blend of the 2 given Vectors
-		/// </summary>
-		/// <param name="a">First input vector</param>
-		/// <param name="b">Second input vector</param>
-		/// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
-		/// <param name="result">a when blend=0, b when blend=1, and a linear combination otherwise</param>
-		public static void Lerp(ref Vector2 a, ref Vector2 b, float blend, out Vector2 result)
-		{
-			result.X = blend * (b.X - a.X) + a.X;
-			result.Y = blend * (b.Y - a.Y) + a.Y;
-		}
-
-		#endregion
-
-		#region Barycentric
-
-		/// <summary>
-		/// Interpolate 3 Vectors using Barycentric coordinates
-		/// </summary>
-		/// <param name="a">First input Vector</param>
-		/// <param name="b">Second input Vector</param>
-		/// <param name="c">Third input Vector</param>
-		/// <param name="u">First Barycentric Coordinate</param>
-		/// <param name="v">Second Barycentric Coordinate</param>
-		/// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
-		public static Vector2 BaryCentric(Vector2 a, Vector2 b, Vector2 c, float u, float v)
-		{
-			return a + u * (b - a) + v * (c - a);
-		}
-
-		/// <summary>Interpolate 3 Vectors using Barycentric coordinates</summary>
-		/// <param name="a">First input Vector.</param>
-		/// <param name="b">Second input Vector.</param>
-		/// <param name="c">Third input Vector.</param>
-		/// <param name="u">First Barycentric Coordinate.</param>
-		/// <param name="v">Second Barycentric Coordinate.</param>
-		/// <param name="result">Output Vector. a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</param>
-		public static void BaryCentric(ref Vector2 a, ref Vector2 b, ref Vector2 c, float u, float v, out Vector2 result)
-		{
-			result = a; // copy
-
-			Vector2 temp = b; // copy
-			Subtract(ref temp, ref a, out temp);
-			Multiply(ref temp, u, out temp);
-			Add(ref result, ref temp, out result);
-
-			temp = c; // copy
-			Subtract(ref temp, ref a, out temp);
-			Multiply(ref temp, v, out temp);
-			Add(ref result, ref temp, out result);
-		}
-
-		#endregion
-
-		#endregion
-
-		#region Operators
-
-		/// <summary>
-		/// Adds the specified instances.
-		/// </summary>
-		/// <param name="left">Left operand.</param>
-		/// <param name="right">Right operand.</param>
-		/// <returns>Result of addition.</returns>
-		public static Vector2 operator +(Vector2 left, Vector2 right)
-		{
-			left.X += right.X;
-			left.Y += right.Y;
-			return left;
-		}
-
-		/// <summary>
-		/// Subtracts the specified instances.
-		/// </summary>
-		/// <param name="left">Left operand.</param>
-		/// <param name="right">Right operand.</param>
-		/// <returns>Result of subtraction.</returns>
-		public static Vector2 operator -(Vector2 left, Vector2 right)
-		{
-			left.X -= right.X;
-			left.Y -= right.Y;
-			return left;
-		}
-
-		/// <summary>
-		/// Negates the specified instance.
-		/// </summary>
-		/// <param name="vec">Operand.</param>
-		/// <returns>Result of negation.</returns>
-		public static Vector2 operator -(Vector2 vec)
-		{
-			vec.X = -vec.X;
-			vec.Y = -vec.Y;
-			return vec;
-		}
-
-		/// <summary>
-		/// Multiplies the specified instance by a scalar.
-		/// </summary>
-		/// <param name="vec">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of multiplication.</returns>
-		public static Vector2 operator *(Vector2 vec, float scale)
-		{
-			vec.X *= scale;
-			vec.Y *= scale;
-			return vec;
-		}
-
-		/// <summary>
-		/// Multiplies the specified instance by a scalar.
-		/// </summary>
-		/// <param name="scale">Left operand.</param>
-		/// <param name="vec">Right operand.</param>
-		/// <returns>Result of multiplication.</returns>
-		public static Vector2 operator *(float scale, Vector2 vec)
-		{
-			vec.X *= scale;
-			vec.Y *= scale;
-			return vec;
-		}
-
-		/// <summary>
-		/// Divides the specified instance by a scalar.
-		/// </summary>
-		/// <param name="vec">Left operand</param>
-		/// <param name="scale">Right operand</param>
-		/// <returns>Result of the division.</returns>
-		public static Vector2 operator /(Vector2 vec, float scale)
-		{
-			float mult = 1.0f / scale;
-			vec.X *= mult;
-			vec.Y *= mult;
-			return vec;
-		}
-
-		/// <summary>
-		/// Compares the specified instances for equality.
-		/// </summary>
-		/// <param name="left">Left operand.</param>
-		/// <param name="right">Right operand.</param>
-		/// <returns>True if both instances are equal; false otherwise.</returns>
-		public static bool operator ==(Vector2 left, Vector2 right)
-		{
-			return left.Equals(right);
-		}
-
-		/// <summary>
-		/// Compares the specified instances for inequality.
-		/// </summary>
-		/// <param name="left">Left operand.</param>
-		/// <param name="right">Right operand.</param>
-		/// <returns>True if both instances are not equal; false otherwise.</returns>
-		public static bool operator !=(Vector2 left, Vector2 right)
-		{
-			return !left.Equals(right);
-		}
-
-		#endregion
-
-		#region Overrides
-
-		#region public override string ToString()
-
-		/// <summary>
-		/// Returns a System.String that represents the current Vector2.
-		/// </summary>
-		/// <returns></returns>
-		public override string ToString()
-		{
-			return String.Format("({0}, {1})", X, Y);
-		}
-
-		#endregion
-
-		#region public override int GetHashCode()
-
-		/// <summary>
-		/// Returns the hashcode for this instance.
-		/// </summary>
-		/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
-		public override int GetHashCode()
-		{
-			return X.GetHashCode() ^ Y.GetHashCode();
-		}
-
-		#endregion
-
-		#region public override bool Equals(object obj)
-
-		/// <summary>
-		/// Indicates whether this instance and a specified object are equal.
-		/// </summary>
-		/// <param name="obj">The object to compare to.</param>
-		/// <returns>True if the instances are equal; false otherwise.</returns>
-		public override bool Equals(object obj)
-		{
-			if (!(obj is Vector2))
-				return false;
-
-			return this.Equals((Vector2)obj);
-		}
-
-		#endregion
-
-		#endregion
-
-		#endregion
-
-		#region IEquatable<Vector2> Members
-
-		/// <summary>Indicates whether the current vector is equal to another vector.</summary>
-		/// <param name="other">A vector to compare with this vector.</param>
-		/// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
-		public bool Equals(Vector2 other)
-		{
-			return
-				X == other.X &&
-				Y == other.Y;
-		}
+    /// <summary>Represents a 2D vector using two single-precision floating-point numbers.</summary>
+    /// <remarks>
+    /// The Vector2 structure is suitable for interoperation with unmanaged code requiring two consecutive floats.
+    /// </remarks>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct Vector2 : IEquatable<Vector2>
+    {
+        #region Fields
+
+        /// <summary>
+        /// The X component of the Vector2.
+        /// </summary>
+        public float X;
+
+        /// <summary>
+        /// The Y component of the Vector2.
+        /// </summary>
+        public float Y;
+
+        #endregion
+
+        #region Constructors
+
+        /// <summary>
+        /// Constructs a new Vector2.
+        /// </summary>
+        /// <param name="x">The x coordinate of the net Vector2.</param>
+        /// <param name="y">The y coordinate of the net Vector2.</param>
+        public Vector2(float x, float y)
+        {
+            X = x;
+            Y = y;
+        }
+
+        /// <summary>
+        /// Constructs a new Vector2 from the given Vector2.
+        /// </summary>
+        /// <param name="v">The Vector2 to copy components from.</param>
+        [Obsolete]
+        public Vector2(Vector2 v)
+        {
+            X = v.X;
+            Y = v.Y;
+        }
+
+        /// <summary>
+        /// Constructs a new Vector2 from the given Vector3.
+        /// </summary>
+        /// <param name="v">The Vector3 to copy components from. Z is discarded.</param>
+        [Obsolete]
+        public Vector2(Vector3 v)
+        {
+            X = v.X;
+            Y = v.Y;
+        }
+
+        /// <summary>
+        /// Constructs a new Vector2 from the given Vector4.
+        /// </summary>
+        /// <param name="v">The Vector4 to copy components from. Z and W are discarded.</param>
+        [Obsolete]
+        public Vector2(Vector4 v)
+        {
+            X = v.X;
+            Y = v.Y;
+        }
+
+        #endregion
+
+        #region Public Members
+
+        #region Instance
+
+        #region public void Add()
+
+        /// <summary>Add the Vector passed as parameter to this instance.</summary>
+        /// <param name="right">Right operand. This parameter is only read from.</param>
+        [Obsolete("Use static Add() method instead.")]
+        public void Add(Vector2 right)
+        {
+            this.X += right.X;
+            this.Y += right.Y;
+        }
+
+        /// <summary>Add the Vector passed as parameter to this instance.</summary>
+        /// <param name="right">Right operand. This parameter is only read from.</param>
+        [CLSCompliant(false)]
+        [Obsolete("Use static Add() method instead.")]
+        public void Add(ref Vector2 right)
+        {
+            this.X += right.X;
+            this.Y += right.Y;
+        }
+
+        #endregion public void Add()
+
+        #region public void Sub()
+
+        /// <summary>Subtract the Vector passed as parameter from this instance.</summary>
+        /// <param name="right">Right operand. This parameter is only read from.</param>
+        [Obsolete("Use static Subtract() method instead.")]
+        public void Sub(Vector2 right)
+        {
+            this.X -= right.X;
+            this.Y -= right.Y;
+        }
+
+        /// <summary>Subtract the Vector passed as parameter from this instance.</summary>
+        /// <param name="right">Right operand. This parameter is only read from.</param>
+        [CLSCompliant(false)]
+        [Obsolete("Use static Subtract() method instead.")]
+        public void Sub(ref Vector2 right)
+        {
+            this.X -= right.X;
+            this.Y -= right.Y;
+        }
+
+        #endregion public void Sub()
+
+        #region public void Mult()
+
+        /// <summary>Multiply this instance by a scalar.</summary>
+        /// <param name="f">Scalar operand.</param>
+        [Obsolete("Use static Multiply() method instead.")]
+        public void Mult(float f)
+        {
+            this.X *= f;
+            this.Y *= f;
+        }
+
+        #endregion public void Mult()
+
+        #region public void Div()
+
+        /// <summary>Divide this instance by a scalar.</summary>
+        /// <param name="f">Scalar operand.</param>
+        [Obsolete("Use static Divide() method instead.")]
+        public void Div(float f)
+        {
+            float mult = 1.0f / f;
+            this.X *= mult;
+            this.Y *= mult;
+        }
+
+        #endregion public void Div()
+
+        #region public float Length
+
+        /// <summary>
+        /// Gets the length (magnitude) of the vector.
+        /// </summary>
+        /// <see cref="LengthFast"/>
+        /// <seealso cref="LengthSquared"/>
+        public float Length
+        {
+            get
+            {
+                return (float)System.Math.Sqrt(X * X + Y * Y);
+            }
+        }
+
+        #endregion
+
+        #region public float LengthFast
+
+        /// <summary>
+        /// Gets an approximation of the vector length (magnitude).
+        /// </summary>
+        /// <remarks>
+        /// This property uses an approximation of the square root function to calculate vector magnitude, with
+        /// an upper error bound of 0.001.
+        /// </remarks>
+        /// <see cref="Length"/>
+        /// <seealso cref="LengthSquared"/>
+        public float LengthFast
+        {
+            get
+            {
+                return 1.0f / MathHelper.InverseSqrtFast(X * X + Y * Y);
+            }
+        }
+
+        #endregion
+
+        #region public float LengthSquared
+
+        /// <summary>
+        /// Gets the square of the vector length (magnitude).
+        /// </summary>
+        /// <remarks>
+        /// This property avoids the costly square root operation required by the Length property. This makes it more suitable
+        /// for comparisons.
+        /// </remarks>
+        /// <see cref="Length"/>
+        /// <seealso cref="LengthFast"/>
+        public float LengthSquared
+        {
+            get
+            {
+                return X * X + Y * Y;
+            }
+        }
+
+        #endregion
+
+        #region public Vector2 PerpendicularRight
+
+        /// <summary>
+        /// Gets the perpendicular vector on the right side of this vector.
+        /// </summary>
+        public Vector2 PerpendicularRight
+        {
+            get
+            {
+                return new Vector2(Y, -X);
+            }
+        }
+
+        #endregion
+
+        #region public Vector2 PerpendicularLeft
+
+        /// <summary>
+        /// Gets the perpendicular vector on the left side of this vector.
+        /// </summary>
+        public Vector2 PerpendicularLeft
+        {
+            get
+            {
+                return new Vector2(-Y, X);
+            }
+        }
+
+        #endregion
+
+        #region public void Normalize()
+
+        /// <summary>
+        /// Scales the Vector2 to unit length.
+        /// </summary>
+        public void Normalize()
+        {
+            float scale = 1.0f / this.Length;
+            X *= scale;
+            Y *= scale;
+        }
+
+        #endregion
+
+        #region public void NormalizeFast()
+
+        /// <summary>
+        /// Scales the Vector2 to approximately unit length.
+        /// </summary>
+        public void NormalizeFast()
+        {
+            float scale = MathHelper.InverseSqrtFast(X * X + Y * Y);
+            X *= scale;
+            Y *= scale;
+        }
+
+        #endregion
+
+        #region public void Scale()
+
+        /// <summary>
+        /// Scales the current Vector2 by the given amounts.
+        /// </summary>
+        /// <param name="sx">The scale of the X component.</param>
+        /// <param name="sy">The scale of the Y component.</param>
+        [Obsolete("Use static Multiply() method instead.")]
+        public void Scale(float sx, float sy)
+        {
+            this.X = X * sx;
+            this.Y = Y * sy;
+        }
+
+        /// <summary>Scales this instance by the given parameter.</summary>
+        /// <param name="scale">The scaling of the individual components.</param>
+        [Obsolete("Use static Multiply() method instead.")]
+        public void Scale(Vector2 scale)
+        {
+            this.X *= scale.X;
+            this.Y *= scale.Y;
+        }
+
+        /// <summary>Scales this instance by the given parameter.</summary>
+        /// <param name="scale">The scaling of the individual components.</param>
+        [CLSCompliant(false)]
+        [Obsolete("Use static Multiply() method instead.")]
+        public void Scale(ref Vector2 scale)
+        {
+            this.X *= scale.X;
+            this.Y *= scale.Y;
+        }
+
+        #endregion public void Scale()
+
+        #endregion
+
+        #region Static
+
+        #region Fields
+
+        /// <summary>
+        /// Defines a unit-length Vector2 that points towards the X-axis.
+        /// </summary>
+        public static readonly Vector2 UnitX = new Vector2(1, 0);
+
+        /// <summary>
+        /// Defines a unit-length Vector2 that points towards the Y-axis.
+        /// </summary>
+        public static readonly Vector2 UnitY = new Vector2(0, 1);
+
+        /// <summary>
+        /// Defines a zero-length Vector2.
+        /// </summary>
+        public static readonly Vector2 Zero = new Vector2(0, 0);
+
+        /// <summary>
+        /// Defines an instance with all components set to 1.
+        /// </summary>
+        public static readonly Vector2 One = new Vector2(1, 1);
+
+        /// <summary>
+        /// Defines the size of the Vector2 struct in bytes.
+        /// </summary>
+        public static readonly int SizeInBytes = Marshal.SizeOf(new Vector2());
+
+        #endregion
+
+        #region Obsolete
+
+        #region Sub
+
+        /// <summary>
+        /// Subtract one Vector from another
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <returns>Result of subtraction</returns>
+        [Obsolete("Use static Subtract() method instead.")]
+        public static Vector2 Sub(Vector2 a, Vector2 b)
+        {
+            a.X -= b.X;
+            a.Y -= b.Y;
+            return a;
+        }
+
+        /// <summary>
+        /// Subtract one Vector from another
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <param name="result">Result of subtraction</param>
+        [Obsolete("Use static Subtract() method instead.")]
+        public static void Sub(ref Vector2 a, ref Vector2 b, out Vector2 result)
+        {
+            result.X = a.X - b.X;
+            result.Y = a.Y - b.Y;
+        }
+
+        #endregion
+
+        #region Mult
+
+        /// <summary>
+        /// Multiply a vector and a scalar
+        /// </summary>
+        /// <param name="a">Vector operand</param>
+        /// <param name="f">Scalar operand</param>
+        /// <returns>Result of the multiplication</returns>
+        [Obsolete("Use static Multiply() method instead.")]
+        public static Vector2 Mult(Vector2 a, float f)
+        {
+            a.X *= f;
+            a.Y *= f;
+            return a;
+        }
+
+        /// <summary>
+        /// Multiply a vector and a scalar
+        /// </summary>
+        /// <param name="a">Vector operand</param>
+        /// <param name="f">Scalar operand</param>
+        /// <param name="result">Result of the multiplication</param>
+        [Obsolete("Use static Multiply() method instead.")]
+        public static void Mult(ref Vector2 a, float f, out Vector2 result)
+        {
+            result.X = a.X * f;
+            result.Y = a.Y * f;
+        }
+
+        #endregion
+
+        #region Div
+
+        /// <summary>
+        /// Divide a vector by a scalar
+        /// </summary>
+        /// <param name="a">Vector operand</param>
+        /// <param name="f">Scalar operand</param>
+        /// <returns>Result of the division</returns>
+        [Obsolete("Use static Divide() method instead.")]
+        public static Vector2 Div(Vector2 a, float f)
+        {
+            float mult = 1.0f / f;
+            a.X *= mult;
+            a.Y *= mult;
+            return a;
+        }
+
+        /// <summary>
+        /// Divide a vector by a scalar
+        /// </summary>
+        /// <param name="a">Vector operand</param>
+        /// <param name="f">Scalar operand</param>
+        /// <param name="result">Result of the division</param>
+        [Obsolete("Use static Divide() method instead.")]
+        public static void Div(ref Vector2 a, float f, out Vector2 result)
+        {
+            float mult = 1.0f / f;
+            result.X = a.X * mult;
+            result.Y = a.Y * mult;
+        }
+
+        #endregion
+
+        #endregion
+
+        #region Add
+
+        /// <summary>
+        /// Adds two vectors.
+        /// </summary>
+        /// <param name="a">Left operand.</param>
+        /// <param name="b">Right operand.</param>
+        /// <returns>Result of operation.</returns>
+        public static Vector2 Add(Vector2 a, Vector2 b)
+        {
+            Add(ref a, ref b, out a);
+            return a;
+        }
+
+        /// <summary>
+        /// Adds two vectors.
+        /// </summary>
+        /// <param name="a">Left operand.</param>
+        /// <param name="b">Right operand.</param>
+        /// <param name="result">Result of operation.</param>
+        public static void Add(ref Vector2 a, ref Vector2 b, out Vector2 result)
+        {
+            result = new Vector2(a.X + b.X, a.Y + b.Y);
+        }
+
+        #endregion
+
+        #region Subtract
+
+        /// <summary>
+        /// Subtract one Vector from another
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <returns>Result of subtraction</returns>
+        public static Vector2 Subtract(Vector2 a, Vector2 b)
+        {
+            Subtract(ref a, ref b, out a);
+            return a;
+        }
+
+        /// <summary>
+        /// Subtract one Vector from another
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <param name="result">Result of subtraction</param>
+        public static void Subtract(ref Vector2 a, ref Vector2 b, out Vector2 result)
+        {
+            result = new Vector2(a.X - b.X, a.Y - b.Y);
+        }
+
+        #endregion
+
+        #region Multiply
+
+        /// <summary>
+        /// Multiplies a vector by a scalar.
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of the operation.</returns>
+        public static Vector2 Multiply(Vector2 vector, float scale)
+        {
+            Multiply(ref vector, scale, out vector);
+            return vector;
+        }
+
+        /// <summary>
+        /// Multiplies a vector by a scalar.
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <param name="result">Result of the operation.</param>
+        public static void Multiply(ref Vector2 vector, float scale, out Vector2 result)
+        {
+            result = new Vector2(vector.X * scale, vector.Y * scale);
+        }
+
+        /// <summary>
+        /// Multiplies a vector by the components a vector (scale).
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of the operation.</returns>
+        public static Vector2 Multiply(Vector2 vector, Vector2 scale)
+        {
+            Multiply(ref vector, ref scale, out vector);
+            return vector;
+        }
+
+        /// <summary>
+        /// Multiplies a vector by the components of a vector (scale).
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <param name="result">Result of the operation.</param>
+        public static void Multiply(ref Vector2 vector, ref Vector2 scale, out Vector2 result)
+        {
+            result = new Vector2(vector.X * scale.X, vector.Y * scale.Y);
+        }
+
+        #endregion
+
+        #region Divide
+
+        /// <summary>
+        /// Divides a vector by a scalar.
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of the operation.</returns>
+        public static Vector2 Divide(Vector2 vector, float scale)
+        {
+            Divide(ref vector, scale, out vector);
+            return vector;
+        }
+
+        /// <summary>
+        /// Divides a vector by a scalar.
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <param name="result">Result of the operation.</param>
+        public static void Divide(ref Vector2 vector, float scale, out Vector2 result)
+        {
+            Multiply(ref vector, 1 / scale, out result);
+        }
+
+        /// <summary>
+        /// Divides a vector by the components of a vector (scale).
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of the operation.</returns>
+        public static Vector2 Divide(Vector2 vector, Vector2 scale)
+        {
+            Divide(ref vector, ref scale, out vector);
+            return vector;
+        }
+
+        /// <summary>
+        /// Divide a vector by the components of a vector (scale).
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <param name="result">Result of the operation.</param>
+        public static void Divide(ref Vector2 vector, ref Vector2 scale, out Vector2 result)
+        {
+            result = new Vector2(vector.X / scale.X, vector.Y / scale.Y);
+        }
+
+        #endregion
+
+        #region ComponentMin
+
+        /// <summary>
+        /// Calculate the component-wise minimum of two vectors
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <returns>The component-wise minimum</returns>
+        public static Vector2 ComponentMin(Vector2 a, Vector2 b)
+        {
+            a.X = a.X < b.X ? a.X : b.X;
+            a.Y = a.Y < b.Y ? a.Y : b.Y;
+            return a;
+        }
+
+        /// <summary>
+        /// Calculate the component-wise minimum of two vectors
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <param name="result">The component-wise minimum</param>
+        public static void ComponentMin(ref Vector2 a, ref Vector2 b, out Vector2 result)
+        {
+            result.X = a.X < b.X ? a.X : b.X;
+            result.Y = a.Y < b.Y ? a.Y : b.Y;
+        }
+
+        #endregion
+
+        #region ComponentMax
+
+        /// <summary>
+        /// Calculate the component-wise maximum of two vectors
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <returns>The component-wise maximum</returns>
+        public static Vector2 ComponentMax(Vector2 a, Vector2 b)
+        {
+            a.X = a.X > b.X ? a.X : b.X;
+            a.Y = a.Y > b.Y ? a.Y : b.Y;
+            return a;
+        }
+
+        /// <summary>
+        /// Calculate the component-wise maximum of two vectors
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <param name="result">The component-wise maximum</param>
+        public static void ComponentMax(ref Vector2 a, ref Vector2 b, out Vector2 result)
+        {
+            result.X = a.X > b.X ? a.X : b.X;
+            result.Y = a.Y > b.Y ? a.Y : b.Y;
+        }
+
+        #endregion
+
+        #region Min
+
+        /// <summary>
+        /// Returns the Vector3 with the minimum magnitude
+        /// </summary>
+        /// <param name="left">Left operand</param>
+        /// <param name="right">Right operand</param>
+        /// <returns>The minimum Vector3</returns>
+        public static Vector2 Min(Vector2 left, Vector2 right)
+        {
+            return left.LengthSquared < right.LengthSquared ? left : right;
+        }
+
+        #endregion
+
+        #region Max
+
+        /// <summary>
+        /// Returns the Vector3 with the minimum magnitude
+        /// </summary>
+        /// <param name="left">Left operand</param>
+        /// <param name="right">Right operand</param>
+        /// <returns>The minimum Vector3</returns>
+        public static Vector2 Max(Vector2 left, Vector2 right)
+        {
+            return left.LengthSquared >= right.LengthSquared ? left : right;
+        }
+
+        #endregion
+
+        #region Clamp
+
+        /// <summary>
+        /// Clamp a vector to the given minimum and maximum vectors
+        /// </summary>
+        /// <param name="vec">Input vector</param>
+        /// <param name="min">Minimum vector</param>
+        /// <param name="max">Maximum vector</param>
+        /// <returns>The clamped vector</returns>
+        public static Vector2 Clamp(Vector2 vec, Vector2 min, Vector2 max)
+        {
+            vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
+            vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
+            return vec;
+        }
+
+        /// <summary>
+        /// Clamp a vector to the given minimum and maximum vectors
+        /// </summary>
+        /// <param name="vec">Input vector</param>
+        /// <param name="min">Minimum vector</param>
+        /// <param name="max">Maximum vector</param>
+        /// <param name="result">The clamped vector</param>
+        public static void Clamp(ref Vector2 vec, ref Vector2 min, ref Vector2 max, out Vector2 result)
+        {
+            result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
+            result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
+        }
+
+        #endregion
+
+        #region Normalize
+
+        /// <summary>
+        /// Scale a vector to unit length
+        /// </summary>
+        /// <param name="vec">The input vector</param>
+        /// <returns>The normalized vector</returns>
+        public static Vector2 Normalize(Vector2 vec)
+        {
+            float scale = 1.0f / vec.Length;
+            vec.X *= scale;
+            vec.Y *= scale;
+            return vec;
+        }
+
+        /// <summary>
+        /// Scale a vector to unit length
+        /// </summary>
+        /// <param name="vec">The input vector</param>
+        /// <param name="result">The normalized vector</param>
+        public static void Normalize(ref Vector2 vec, out Vector2 result)
+        {
+            float scale = 1.0f / vec.Length;
+            result.X = vec.X * scale;
+            result.Y = vec.Y * scale;
+        }
+
+        #endregion
+
+        #region NormalizeFast
+
+        /// <summary>
+        /// Scale a vector to approximately unit length
+        /// </summary>
+        /// <param name="vec">The input vector</param>
+        /// <returns>The normalized vector</returns>
+        public static Vector2 NormalizeFast(Vector2 vec)
+        {
+            float scale = MathHelper.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
+            vec.X *= scale;
+            vec.Y *= scale;
+            return vec;
+        }
+
+        /// <summary>
+        /// Scale a vector to approximately unit length
+        /// </summary>
+        /// <param name="vec">The input vector</param>
+        /// <param name="result">The normalized vector</param>
+        public static void NormalizeFast(ref Vector2 vec, out Vector2 result)
+        {
+            float scale = MathHelper.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
+            result.X = vec.X * scale;
+            result.Y = vec.Y * scale;
+        }
+
+        #endregion
+
+        #region Dot
+
+        /// <summary>
+        /// Calculate the dot (scalar) product of two vectors
+        /// </summary>
+        /// <param name="left">First operand</param>
+        /// <param name="right">Second operand</param>
+        /// <returns>The dot product of the two inputs</returns>
+        public static float Dot(Vector2 left, Vector2 right)
+        {
+            return left.X * right.X + left.Y * right.Y;
+        }
+
+        /// <summary>
+        /// Calculate the dot (scalar) product of two vectors
+        /// </summary>
+        /// <param name="left">First operand</param>
+        /// <param name="right">Second operand</param>
+        /// <param name="result">The dot product of the two inputs</param>
+        public static void Dot(ref Vector2 left, ref Vector2 right, out float result)
+        {
+            result = left.X * right.X + left.Y * right.Y;
+        }
+
+        #endregion
+
+        #region Lerp
+
+        /// <summary>
+        /// Returns a new Vector that is the linear blend of the 2 given Vectors
+        /// </summary>
+        /// <param name="a">First input vector</param>
+        /// <param name="b">Second input vector</param>
+        /// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
+        /// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
+        public static Vector2 Lerp(Vector2 a, Vector2 b, float blend)
+        {
+            a.X = blend * (b.X - a.X) + a.X;
+            a.Y = blend * (b.Y - a.Y) + a.Y;
+            return a;
+        }
+
+        /// <summary>
+        /// Returns a new Vector that is the linear blend of the 2 given Vectors
+        /// </summary>
+        /// <param name="a">First input vector</param>
+        /// <param name="b">Second input vector</param>
+        /// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
+        /// <param name="result">a when blend=0, b when blend=1, and a linear combination otherwise</param>
+        public static void Lerp(ref Vector2 a, ref Vector2 b, float blend, out Vector2 result)
+        {
+            result.X = blend * (b.X - a.X) + a.X;
+            result.Y = blend * (b.Y - a.Y) + a.Y;
+        }
+
+        #endregion
+
+        #region Barycentric
+
+        /// <summary>
+        /// Interpolate 3 Vectors using Barycentric coordinates
+        /// </summary>
+        /// <param name="a">First input Vector</param>
+        /// <param name="b">Second input Vector</param>
+        /// <param name="c">Third input Vector</param>
+        /// <param name="u">First Barycentric Coordinate</param>
+        /// <param name="v">Second Barycentric Coordinate</param>
+        /// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
+        public static Vector2 BaryCentric(Vector2 a, Vector2 b, Vector2 c, float u, float v)
+        {
+            return a + u * (b - a) + v * (c - a);
+        }
+
+        /// <summary>Interpolate 3 Vectors using Barycentric coordinates</summary>
+        /// <param name="a">First input Vector.</param>
+        /// <param name="b">Second input Vector.</param>
+        /// <param name="c">Third input Vector.</param>
+        /// <param name="u">First Barycentric Coordinate.</param>
+        /// <param name="v">Second Barycentric Coordinate.</param>
+        /// <param name="result">Output Vector. a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</param>
+        public static void BaryCentric(ref Vector2 a, ref Vector2 b, ref Vector2 c, float u, float v, out Vector2 result)
+        {
+            result = a; // copy
+
+            Vector2 temp = b; // copy
+            Subtract(ref temp, ref a, out temp);
+            Multiply(ref temp, u, out temp);
+            Add(ref result, ref temp, out result);
+
+            temp = c; // copy
+            Subtract(ref temp, ref a, out temp);
+            Multiply(ref temp, v, out temp);
+            Add(ref result, ref temp, out result);
+        }
+
+        #endregion
+
+        #endregion
+
+        #region Operators
+
+        /// <summary>
+        /// Adds the specified instances.
+        /// </summary>
+        /// <param name="left">Left operand.</param>
+        /// <param name="right">Right operand.</param>
+        /// <returns>Result of addition.</returns>
+        public static Vector2 operator +(Vector2 left, Vector2 right)
+        {
+            left.X += right.X;
+            left.Y += right.Y;
+            return left;
+        }
+
+        /// <summary>
+        /// Subtracts the specified instances.
+        /// </summary>
+        /// <param name="left">Left operand.</param>
+        /// <param name="right">Right operand.</param>
+        /// <returns>Result of subtraction.</returns>
+        public static Vector2 operator -(Vector2 left, Vector2 right)
+        {
+            left.X -= right.X;
+            left.Y -= right.Y;
+            return left;
+        }
+
+        /// <summary>
+        /// Negates the specified instance.
+        /// </summary>
+        /// <param name="vec">Operand.</param>
+        /// <returns>Result of negation.</returns>
+        public static Vector2 operator -(Vector2 vec)
+        {
+            vec.X = -vec.X;
+            vec.Y = -vec.Y;
+            return vec;
+        }
+
+        /// <summary>
+        /// Multiplies the specified instance by a scalar.
+        /// </summary>
+        /// <param name="vec">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of multiplication.</returns>
+        public static Vector2 operator *(Vector2 vec, float scale)
+        {
+            vec.X *= scale;
+            vec.Y *= scale;
+            return vec;
+        }
+
+        /// <summary>
+        /// Multiplies the specified instance by a scalar.
+        /// </summary>
+        /// <param name="scale">Left operand.</param>
+        /// <param name="vec">Right operand.</param>
+        /// <returns>Result of multiplication.</returns>
+        public static Vector2 operator *(float scale, Vector2 vec)
+        {
+            vec.X *= scale;
+            vec.Y *= scale;
+            return vec;
+        }
+
+        /// <summary>
+        /// Divides the specified instance by a scalar.
+        /// </summary>
+        /// <param name="vec">Left operand</param>
+        /// <param name="scale">Right operand</param>
+        /// <returns>Result of the division.</returns>
+        public static Vector2 operator /(Vector2 vec, float scale)
+        {
+            float mult = 1.0f / scale;
+            vec.X *= mult;
+            vec.Y *= mult;
+            return vec;
+        }
+
+        /// <summary>
+        /// Compares the specified instances for equality.
+        /// </summary>
+        /// <param name="left">Left operand.</param>
+        /// <param name="right">Right operand.</param>
+        /// <returns>True if both instances are equal; false otherwise.</returns>
+        public static bool operator ==(Vector2 left, Vector2 right)
+        {
+            return left.Equals(right);
+        }
+
+        /// <summary>
+        /// Compares the specified instances for inequality.
+        /// </summary>
+        /// <param name="left">Left operand.</param>
+        /// <param name="right">Right operand.</param>
+        /// <returns>True if both instances are not equal; false otherwise.</returns>
+        public static bool operator !=(Vector2 left, Vector2 right)
+        {
+            return !left.Equals(right);
+        }
+
+        #endregion
+
+        #region Overrides
+
+        #region public override string ToString()
+
+        /// <summary>
+        /// Returns a System.String that represents the current Vector2.
+        /// </summary>
+        /// <returns></returns>
+        public override string ToString()
+        {
+            return String.Format("({0}, {1})", X, Y);
+        }
+
+        #endregion
+
+        #region public override int GetHashCode()
+
+        /// <summary>
+        /// Returns the hashcode for this instance.
+        /// </summary>
+        /// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
+        public override int GetHashCode()
+        {
+            return X.GetHashCode() ^ Y.GetHashCode();
+        }
+
+        #endregion
+
+        #region public override bool Equals(object obj)
+
+        /// <summary>
+        /// Indicates whether this instance and a specified object are equal.
+        /// </summary>
+        /// <param name="obj">The object to compare to.</param>
+        /// <returns>True if the instances are equal; false otherwise.</returns>
+        public override bool Equals(object obj)
+        {
+            if (!(obj is Vector2))
+                return false;
+
+            return this.Equals((Vector2)obj);
+        }
+
+        #endregion
+
+        #endregion
+
+        #endregion
+
+        #region IEquatable<Vector2> Members
+
+        /// <summary>Indicates whether the current vector is equal to another vector.</summary>
+        /// <param name="other">A vector to compare with this vector.</param>
+        /// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
+        public bool Equals(Vector2 other)
+        {
+            return
+                X == other.X &&
+                Y == other.Y;
+        }
 
         #endregion
 

+ 1156 - 1156
Script/AtomicNET/AtomicNET/Math/Vector4.cs

@@ -27,1160 +27,1160 @@ using System.Runtime.InteropServices;
 
 namespace AtomicEngine
 {
-	/// <summary>Represents a 4D vector using four single-precision floating-point numbers.</summary>
-	/// <remarks>
-	/// The Vector4 structure is suitable for interoperation with unmanaged code requiring four consecutive floats.
-	/// </remarks>
-	[StructLayout(LayoutKind.Sequential)]
-	public struct Vector4 : IEquatable<Vector4>
-	{
-		#region Fields
-
-		/// <summary>
-		/// The X component of the Vector4.
-		/// </summary>
-		public float X;
-
-		/// <summary>
-		/// The Y component of the Vector4.
-		/// </summary>
-		public float Y;
-
-		/// <summary>
-		/// The Z component of the Vector4.
-		/// </summary>
-		public float Z;
-
-		/// <summary>
-		/// The W component of the Vector4.
-		/// </summary>
-		public float W;
-
-		/// <summary>
-		/// Defines a unit-length Vector4 that points towards the X-axis.
-		/// </summary>
-		public static Vector4 UnitX = new Vector4(1, 0, 0, 0);
-
-		/// <summary>
-		/// Defines a unit-length Vector4 that points towards the Y-axis.
-		/// </summary>
-		public static Vector4 UnitY = new Vector4(0, 1, 0, 0);
-
-		/// <summary>
-		/// Defines a unit-length Vector4 that points towards the Z-axis.
-		/// </summary>
-		public static Vector4 UnitZ = new Vector4(0, 0, 1, 0);
-
-		/// <summary>
-		/// Defines a unit-length Vector4 that points towards the W-axis.
-		/// </summary>
-		public static Vector4 UnitW = new Vector4(0, 0, 0, 1);
-
-		/// <summary>
-		/// Defines a zero-length Vector4.
-		/// </summary>
-		public static Vector4 Zero = new Vector4(0, 0, 0, 0);
-
-		/// <summary>
-		/// Defines an instance with all components set to 1.
-		/// </summary>
-		public static readonly Vector4 One = new Vector4(1, 1, 1, 1);
-
-		/// <summary>
-		/// Defines the size of the Vector4 struct in bytes.
-		/// </summary>
-		public static readonly int SizeInBytes = Marshal.SizeOf(new Vector4());
-
-		#endregion
-
-		#region Constructors
-
-		/// <summary>
-		/// Constructs a new Vector4.
-		/// </summary>
-		/// <param name="x">The x component of the Vector4.</param>
-		/// <param name="y">The y component of the Vector4.</param>
-		/// <param name="z">The z component of the Vector4.</param>
-		/// <param name="w">The z component of the Vector4.</param>
-		public Vector4(float x, float y, float z, float w)
-		{
-			X = x;
-			Y = y;
-			Z = z;
-			W = w;
-		}
-
-		/// <summary>
-		/// Constructs a new Vector4 from the given Vector2.
-		/// </summary>
-		/// <param name="v">The Vector2 to copy components from.</param>
-		public Vector4(Vector2 v)
-		{
-			X = v.X;
-			Y = v.Y;
-			Z = 0.0f;
-			W = 0.0f;
-		}
-
-		/// <summary>
-		/// Constructs a new Vector4 from the given Vector3.
-		/// </summary>
-		/// <param name="v">The Vector3 to copy components from.</param>
-		public Vector4(Vector3 v)
-		{
-			X = v.X;
-			Y = v.Y;
-			Z = v.Z;
-			W = 0.0f;
-		}
-
-		/// <summary>
-		/// Constructs a new Vector4 from the specified Vector3 and W component.
-		/// </summary>
-		/// <param name="v">The Vector3 to copy components from.</param>
-		/// <param name="w">The W component of the new Vector4.</param>
-		public Vector4(Vector3 v, float w)
-		{
-			X = v.X;
-			Y = v.Y;
-			Z = v.Z;
-			W = w;
-		}
-
-		/// <summary>
-		/// Constructs a new Vector4 from the given Vector4.
-		/// </summary>
-		/// <param name="v">The Vector4 to copy components from.</param>
-		public Vector4(Vector4 v)
-		{
-			X = v.X;
-			Y = v.Y;
-			Z = v.Z;
-			W = v.W;
-		}
-
-		#endregion
-
-		#region Public Members
-
-		#region Instance
-
-		#region public void Add()
-
-		/// <summary>Add the Vector passed as parameter to this instance.</summary>
-		/// <param name="right">Right operand. This parameter is only read from.</param>
-		[Obsolete("Use static Add() method instead.")]
-		public void Add(Vector4 right)
-		{
-			this.X += right.X;
-			this.Y += right.Y;
-			this.Z += right.Z;
-			this.W += right.W;
-		}
-
-		/// <summary>Add the Vector passed as parameter to this instance.</summary>
-		/// <param name="right">Right operand. This parameter is only read from.</param>
-		[CLSCompliant(false)]
-		[Obsolete("Use static Add() method instead.")]
-		public void Add(ref Vector4 right)
-		{
-			this.X += right.X;
-			this.Y += right.Y;
-			this.Z += right.Z;
-			this.W += right.W;
-		}
-
-		#endregion public void Add()
-
-		#region public void Sub()
-
-		/// <summary>Subtract the Vector passed as parameter from this instance.</summary>
-		/// <param name="right">Right operand. This parameter is only read from.</param>
-		[Obsolete("Use static Subtract() method instead.")]
-		public void Sub(Vector4 right)
-		{
-			this.X -= right.X;
-			this.Y -= right.Y;
-			this.Z -= right.Z;
-			this.W -= right.W;
-		}
-
-		/// <summary>Subtract the Vector passed as parameter from this instance.</summary>
-		/// <param name="right">Right operand. This parameter is only read from.</param>
-		[CLSCompliant(false)]
-		[Obsolete("Use static Subtract() method instead.")]
-		public void Sub(ref Vector4 right)
-		{
-			this.X -= right.X;
-			this.Y -= right.Y;
-			this.Z -= right.Z;
-			this.W -= right.W;
-		}
-
-		#endregion public void Sub()
-
-		#region public void Mult()
-
-		/// <summary>Multiply this instance by a scalar.</summary>
-		/// <param name="f">Scalar operand.</param>
-		[Obsolete("Use static Multiply() method instead.")]
-		public void Mult(float f)
-		{
-			this.X *= f;
-			this.Y *= f;
-			this.Z *= f;
-			this.W *= f;
-		}
-
-		#endregion public void Mult()
-
-		#region public void Div()
-
-		/// <summary>Divide this instance by a scalar.</summary>
-		/// <param name="f">Scalar operand.</param>
-		[Obsolete("Use static Divide() method instead.")]
-		public void Div(float f)
-		{
-			float mult = 1.0f / f;
-			this.X *= mult;
-			this.Y *= mult;
-			this.Z *= mult;
-			this.W *= mult;
-		}
-
-		#endregion public void Div()
-
-		#region public float Length
-
-		/// <summary>
-		/// Gets the length (magnitude) of the vector.
-		/// </summary>
-		/// <see cref="LengthFast"/>
-		/// <seealso cref="LengthSquared"/>
-		public float Length
-		{
-			get
-			{
-				return (float)System.Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
-			}
-		}
-
-		#endregion
-
-		#region public float LengthFast
-
-		/// <summary>
-		/// Gets an approximation of the vector length (magnitude).
-		/// </summary>
-		/// <remarks>
-		/// This property uses an approximation of the square root function to calculate vector magnitude, with
-		/// an upper error bound of 0.001.
-		/// </remarks>
-		/// <see cref="Length"/>
-		/// <seealso cref="LengthSquared"/>
-		public float LengthFast
-		{
-			get
-			{
-				return 1.0f / MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z + W * W);
-			}
-		}
-
-		#endregion
-
-		#region public float LengthSquared
-
-		/// <summary>
-		/// Gets the square of the vector length (magnitude).
-		/// </summary>
-		/// <remarks>
-		/// This property avoids the costly square root operation required by the Length property. This makes it more suitable
-		/// for comparisons.
-		/// </remarks>
-		/// <see cref="Length"/>
-		/// <seealso cref="LengthFast"/>
-		public float LengthSquared
-		{
-			get
-			{
-				return X * X + Y * Y + Z * Z + W * W;
-			}
-		}
-
-		#endregion
-
-		#region public void Normalize()
-
-		/// <summary>
-		/// Scales the Vector4 to unit length.
-		/// </summary>
-		public void Normalize()
-		{
-			float scale = 1.0f / this.Length;
-			X *= scale;
-			Y *= scale;
-			Z *= scale;
-			W *= scale;
-		}
-
-		#endregion
-
-		#region public void NormalizeFast()
-
-		/// <summary>
-		/// Scales the Vector4 to approximately unit length.
-		/// </summary>
-		public void NormalizeFast()
-		{
-			float scale = MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z + W * W);
-			X *= scale;
-			Y *= scale;
-			Z *= scale;
-			W *= scale;
-		}
-
-		#endregion
-
-		#region public void Scale()
-
-		/// <summary>
-		/// Scales the current Vector4 by the given amounts.
-		/// </summary>
-		/// <param name="sx">The scale of the X component.</param>
-		/// <param name="sy">The scale of the Y component.</param>
-		/// <param name="sz">The scale of the Z component.</param>
-		/// <param name="sw">The scale of the Z component.</param>
-		[Obsolete("Use static Multiply() method instead.")]
-		public void Scale(float sx, float sy, float sz, float sw)
-		{
-			this.X = X * sx;
-			this.Y = Y * sy;
-			this.Z = Z * sz;
-			this.W = W * sw;
-		}
-
-		/// <summary>Scales this instance by the given parameter.</summary>
-		/// <param name="scale">The scaling of the individual components.</param>
-		[Obsolete("Use static Multiply() method instead.")]
-		public void Scale(Vector4 scale)
-		{
-			this.X *= scale.X;
-			this.Y *= scale.Y;
-			this.Z *= scale.Z;
-			this.W *= scale.W;
-		}
-
-		/// <summary>Scales this instance by the given parameter.</summary>
-		/// <param name="scale">The scaling of the individual components.</param>
-		[CLSCompliant(false)]
-		[Obsolete("Use static Multiply() method instead.")]
-		public void Scale(ref Vector4 scale)
-		{
-			this.X *= scale.X;
-			this.Y *= scale.Y;
-			this.Z *= scale.Z;
-			this.W *= scale.W;
-		}
-
-		#endregion public void Scale()
-
-		#endregion
-
-		#region Static
-
-		#region Obsolete
-
-		#region Sub
-
-		/// <summary>
-		/// Subtract one Vector from another
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <returns>Result of subtraction</returns>
-		public static Vector4 Sub(Vector4 a, Vector4 b)
-		{
-			a.X -= b.X;
-			a.Y -= b.Y;
-			a.Z -= b.Z;
-			a.W -= b.W;
-			return a;
-		}
-
-		/// <summary>
-		/// Subtract one Vector from another
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <param name="result">Result of subtraction</param>
-		public static void Sub(ref Vector4 a, ref Vector4 b, out Vector4 result)
-		{
-			result.X = a.X - b.X;
-			result.Y = a.Y - b.Y;
-			result.Z = a.Z - b.Z;
-			result.W = a.W - b.W;
-		}
-
-		#endregion
-
-		#region Mult
-
-		/// <summary>
-		/// Multiply a vector and a scalar
-		/// </summary>
-		/// <param name="a">Vector operand</param>
-		/// <param name="f">Scalar operand</param>
-		/// <returns>Result of the multiplication</returns>
-		public static Vector4 Mult(Vector4 a, float f)
-		{
-			a.X *= f;
-			a.Y *= f;
-			a.Z *= f;
-			a.W *= f;
-			return a;
-		}
-
-		/// <summary>
-		/// Multiply a vector and a scalar
-		/// </summary>
-		/// <param name="a">Vector operand</param>
-		/// <param name="f">Scalar operand</param>
-		/// <param name="result">Result of the multiplication</param>
-		public static void Mult(ref Vector4 a, float f, out Vector4 result)
-		{
-			result.X = a.X * f;
-			result.Y = a.Y * f;
-			result.Z = a.Z * f;
-			result.W = a.W * f;
-		}
-
-		#endregion
-
-		#region Div
-
-		/// <summary>
-		/// Divide a vector by a scalar
-		/// </summary>
-		/// <param name="a">Vector operand</param>
-		/// <param name="f">Scalar operand</param>
-		/// <returns>Result of the division</returns>
-		public static Vector4 Div(Vector4 a, float f)
-		{
-			float mult = 1.0f / f;
-			a.X *= mult;
-			a.Y *= mult;
-			a.Z *= mult;
-			a.W *= mult;
-			return a;
-		}
-
-		/// <summary>
-		/// Divide a vector by a scalar
-		/// </summary>
-		/// <param name="a">Vector operand</param>
-		/// <param name="f">Scalar operand</param>
-		/// <param name="result">Result of the division</param>
-		public static void Div(ref Vector4 a, float f, out Vector4 result)
-		{
-			float mult = 1.0f / f;
-			result.X = a.X * mult;
-			result.Y = a.Y * mult;
-			result.Z = a.Z * mult;
-			result.W = a.W * mult;
-		}
-
-		#endregion
-
-		#endregion
-
-		#region Add
-
-		/// <summary>
-		/// Adds two vectors.
-		/// </summary>
-		/// <param name="a">Left operand.</param>
-		/// <param name="b">Right operand.</param>
-		/// <returns>Result of operation.</returns>
-		public static Vector4 Add(Vector4 a, Vector4 b)
-		{
-			Add(ref a, ref b, out a);
-			return a;
-		}
-
-		/// <summary>
-		/// Adds two vectors.
-		/// </summary>
-		/// <param name="a">Left operand.</param>
-		/// <param name="b">Right operand.</param>
-		/// <param name="result">Result of operation.</param>
-		public static void Add(ref Vector4 a, ref Vector4 b, out Vector4 result)
-		{
-			result = new Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W);
-		}
-
-		#endregion
-
-		#region Subtract
-
-		/// <summary>
-		/// Subtract one Vector from another
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <returns>Result of subtraction</returns>
-		public static Vector4 Subtract(Vector4 a, Vector4 b)
-		{
-			Subtract(ref a, ref b, out a);
-			return a;
-		}
-
-		/// <summary>
-		/// Subtract one Vector from another
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <param name="result">Result of subtraction</param>
-		public static void Subtract(ref Vector4 a, ref Vector4 b, out Vector4 result)
-		{
-			result = new Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W);
-		}
-
-		#endregion
-
-		#region Multiply
-
-		/// <summary>
-		/// Multiplies a vector by a scalar.
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of the operation.</returns>
-		public static Vector4 Multiply(Vector4 vector, float scale)
-		{
-			Multiply(ref vector, scale, out vector);
-			return vector;
-		}
-
-		/// <summary>
-		/// Multiplies a vector by a scalar.
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <param name="result">Result of the operation.</param>
-		public static void Multiply(ref Vector4 vector, float scale, out Vector4 result)
-		{
-			result = new Vector4(vector.X * scale, vector.Y * scale, vector.Z * scale, vector.W * scale);
-		}
-
-		/// <summary>
-		/// Multiplies a vector by the components a vector (scale).
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of the operation.</returns>
-		public static Vector4 Multiply(Vector4 vector, Vector4 scale)
-		{
-			Multiply(ref vector, ref scale, out vector);
-			return vector;
-		}
-
-		/// <summary>
-		/// Multiplies a vector by the components of a vector (scale).
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <param name="result">Result of the operation.</param>
-		public static void Multiply(ref Vector4 vector, ref Vector4 scale, out Vector4 result)
-		{
-			result = new Vector4(vector.X * scale.X, vector.Y * scale.Y, vector.Z * scale.Z, vector.W * scale.W);
-		}
-
-		#endregion
-
-		#region Divide
-
-		/// <summary>
-		/// Divides a vector by a scalar.
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of the operation.</returns>
-		public static Vector4 Divide(Vector4 vector, float scale)
-		{
-			Divide(ref vector, scale, out vector);
-			return vector;
-		}
-
-		/// <summary>
-		/// Divides a vector by a scalar.
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <param name="result">Result of the operation.</param>
-		public static void Divide(ref Vector4 vector, float scale, out Vector4 result)
-		{
-			Multiply(ref vector, 1 / scale, out result);
-		}
-
-		/// <summary>
-		/// Divides a vector by the components of a vector (scale).
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <returns>Result of the operation.</returns>
-		public static Vector4 Divide(Vector4 vector, Vector4 scale)
-		{
-			Divide(ref vector, ref scale, out vector);
-			return vector;
-		}
-
-		/// <summary>
-		/// Divide a vector by the components of a vector (scale).
-		/// </summary>
-		/// <param name="vector">Left operand.</param>
-		/// <param name="scale">Right operand.</param>
-		/// <param name="result">Result of the operation.</param>
-		public static void Divide(ref Vector4 vector, ref Vector4 scale, out Vector4 result)
-		{
-			result = new Vector4(vector.X / scale.X, vector.Y / scale.Y, vector.Z / scale.Z, vector.W / scale.W);
-		}
-
-		#endregion
-
-		#region Min
-
-		/// <summary>
-		/// Calculate the component-wise minimum of two vectors
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <returns>The component-wise minimum</returns>
-		public static Vector4 Min(Vector4 a, Vector4 b)
-		{
-			a.X = a.X < b.X ? a.X : b.X;
-			a.Y = a.Y < b.Y ? a.Y : b.Y;
-			a.Z = a.Z < b.Z ? a.Z : b.Z;
-			a.W = a.W < b.W ? a.W : b.W;
-			return a;
-		}
-
-		/// <summary>
-		/// Calculate the component-wise minimum of two vectors
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <param name="result">The component-wise minimum</param>
-		public static void Min(ref Vector4 a, ref Vector4 b, out Vector4 result)
-		{
-			result.X = a.X < b.X ? a.X : b.X;
-			result.Y = a.Y < b.Y ? a.Y : b.Y;
-			result.Z = a.Z < b.Z ? a.Z : b.Z;
-			result.W = a.W < b.W ? a.W : b.W;
-		}
-
-		#endregion
-
-		#region Max
-
-		/// <summary>
-		/// Calculate the component-wise maximum of two vectors
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <returns>The component-wise maximum</returns>
-		public static Vector4 Max(Vector4 a, Vector4 b)
-		{
-			a.X = a.X > b.X ? a.X : b.X;
-			a.Y = a.Y > b.Y ? a.Y : b.Y;
-			a.Z = a.Z > b.Z ? a.Z : b.Z;
-			a.W = a.W > b.W ? a.W : b.W;
-			return a;
-		}
-
-		/// <summary>
-		/// Calculate the component-wise maximum of two vectors
-		/// </summary>
-		/// <param name="a">First operand</param>
-		/// <param name="b">Second operand</param>
-		/// <param name="result">The component-wise maximum</param>
-		public static void Max(ref Vector4 a, ref Vector4 b, out Vector4 result)
-		{
-			result.X = a.X > b.X ? a.X : b.X;
-			result.Y = a.Y > b.Y ? a.Y : b.Y;
-			result.Z = a.Z > b.Z ? a.Z : b.Z;
-			result.W = a.W > b.W ? a.W : b.W;
-		}
-
-		#endregion
-
-		#region Clamp
-
-		/// <summary>
-		/// Clamp a vector to the given minimum and maximum vectors
-		/// </summary>
-		/// <param name="vec">Input vector</param>
-		/// <param name="min">Minimum vector</param>
-		/// <param name="max">Maximum vector</param>
-		/// <returns>The clamped vector</returns>
-		public static Vector4 Clamp(Vector4 vec, Vector4 min, Vector4 max)
-		{
-			vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
-			vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
-			vec.Z = vec.X < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
-			vec.W = vec.Y < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
-			return vec;
-		}
-
-		/// <summary>
-		/// Clamp a vector to the given minimum and maximum vectors
-		/// </summary>
-		/// <param name="vec">Input vector</param>
-		/// <param name="min">Minimum vector</param>
-		/// <param name="max">Maximum vector</param>
-		/// <param name="result">The clamped vector</param>
-		public static void Clamp(ref Vector4 vec, ref Vector4 min, ref Vector4 max, out Vector4 result)
-		{
-			result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
-			result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
-			result.Z = vec.X < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
-			result.W = vec.Y < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
-		}
-
-		#endregion
-
-		#region Normalize
-
-		/// <summary>
-		/// Scale a vector to unit length
-		/// </summary>
-		/// <param name="vec">The input vector</param>
-		/// <returns>The normalized vector</returns>
-		public static Vector4 Normalize(Vector4 vec)
-		{
-			float scale = 1.0f / vec.Length;
-			vec.X *= scale;
-			vec.Y *= scale;
-			vec.Z *= scale;
-			vec.W *= scale;
-			return vec;
-		}
-
-		/// <summary>
-		/// Scale a vector to unit length
-		/// </summary>
-		/// <param name="vec">The input vector</param>
-		/// <param name="result">The normalized vector</param>
-		public static void Normalize(ref Vector4 vec, out Vector4 result)
-		{
-			float scale = 1.0f / vec.Length;
-			result.X = vec.X * scale;
-			result.Y = vec.Y * scale;
-			result.Z = vec.Z * scale;
-			result.W = vec.W * scale;
-		}
-
-		#endregion
-
-		#region NormalizeFast
-
-		/// <summary>
-		/// Scale a vector to approximately unit length
-		/// </summary>
-		/// <param name="vec">The input vector</param>
-		/// <returns>The normalized vector</returns>
-		public static Vector4 NormalizeFast(Vector4 vec)
-		{
-			float scale = MathHelper.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y + vec.Z * vec.Z + vec.W * vec.W);
-			vec.X *= scale;
-			vec.Y *= scale;
-			vec.Z *= scale;
-			vec.W *= scale;
-			return vec;
-		}
-
-		/// <summary>
-		/// Scale a vector to approximately unit length
-		/// </summary>
-		/// <param name="vec">The input vector</param>
-		/// <param name="result">The normalized vector</param>
-		public static void NormalizeFast(ref Vector4 vec, out Vector4 result)
-		{
-			float scale = MathHelper.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y + vec.Z * vec.Z + vec.W * vec.W);
-			result.X = vec.X * scale;
-			result.Y = vec.Y * scale;
-			result.Z = vec.Z * scale;
-			result.W = vec.W * scale;
-		}
-
-		#endregion
-
-		#region Dot
-
-		/// <summary>
-		/// Calculate the dot product of two vectors
-		/// </summary>
-		/// <param name="left">First operand</param>
-		/// <param name="right">Second operand</param>
-		/// <returns>The dot product of the two inputs</returns>
-		public static float Dot(Vector4 left, Vector4 right)
-		{
-			return left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
-		}
-
-		/// <summary>
-		/// Calculate the dot product of two vectors
-		/// </summary>
-		/// <param name="left">First operand</param>
-		/// <param name="right">Second operand</param>
-		/// <param name="result">The dot product of the two inputs</param>
-		public static void Dot(ref Vector4 left, ref Vector4 right, out float result)
-		{
-			result = left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
-		}
-
-		#endregion
-
-		#region Lerp
-
-		/// <summary>
-		/// Returns a new Vector that is the linear blend of the 2 given Vectors
-		/// </summary>
-		/// <param name="a">First input vector</param>
-		/// <param name="b">Second input vector</param>
-		/// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
-		/// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
-		public static Vector4 Lerp(Vector4 a, Vector4 b, float blend)
-		{
-			a.X = blend * (b.X - a.X) + a.X;
-			a.Y = blend * (b.Y - a.Y) + a.Y;
-			a.Z = blend * (b.Z - a.Z) + a.Z;
-			a.W = blend * (b.W - a.W) + a.W;
-			return a;
-		}
-
-		/// <summary>
-		/// Returns a new Vector that is the linear blend of the 2 given Vectors
-		/// </summary>
-		/// <param name="a">First input vector</param>
-		/// <param name="b">Second input vector</param>
-		/// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
-		/// <param name="result">a when blend=0, b when blend=1, and a linear combination otherwise</param>
-		public static void Lerp(ref Vector4 a, ref Vector4 b, float blend, out Vector4 result)
-		{
-			result.X = blend * (b.X - a.X) + a.X;
-			result.Y = blend * (b.Y - a.Y) + a.Y;
-			result.Z = blend * (b.Z - a.Z) + a.Z;
-			result.W = blend * (b.W - a.W) + a.W;
-		}
-
-		#endregion
-
-		#region Barycentric
-
-		/// <summary>
-		/// Interpolate 3 Vectors using Barycentric coordinates
-		/// </summary>
-		/// <param name="a">First input Vector</param>
-		/// <param name="b">Second input Vector</param>
-		/// <param name="c">Third input Vector</param>
-		/// <param name="u">First Barycentric Coordinate</param>
-		/// <param name="v">Second Barycentric Coordinate</param>
-		/// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
-		public static Vector4 BaryCentric(Vector4 a, Vector4 b, Vector4 c, float u, float v)
-		{
-			return a + u * (b - a) + v * (c - a);
-		}
-
-		/// <summary>Interpolate 3 Vectors using Barycentric coordinates</summary>
-		/// <param name="a">First input Vector.</param>
-		/// <param name="b">Second input Vector.</param>
-		/// <param name="c">Third input Vector.</param>
-		/// <param name="u">First Barycentric Coordinate.</param>
-		/// <param name="v">Second Barycentric Coordinate.</param>
-		/// <param name="result">Output Vector. a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</param>
-		public static void BaryCentric(ref Vector4 a, ref Vector4 b, ref Vector4 c, float u, float v, out Vector4 result)
-		{
-			result = a; // copy
-
-			Vector4 temp = b; // copy
-			Subtract(ref temp, ref a, out temp);
-			Multiply(ref temp, u, out temp);
-			Add(ref result, ref temp, out result);
-
-			temp = c; // copy
-			Subtract(ref temp, ref a, out temp);
-			Multiply(ref temp, v, out temp);
-			Add(ref result, ref temp, out result);
-		}
-
-		#endregion
-
-		#region Transform
-
-		/// <summary>Transform a Vector by the given Matrix</summary>
-		/// <param name="vec">The vector to transform</param>
-		/// <param name="mat">The desired transformation</param>
-		/// <returns>The transformed vector</returns>
-		public static Vector4 Transform(Vector4 vec, Matrix4 mat)
-		{
-			Vector4 result;
-			result.X = Vector4.Dot(vec, mat.Column0);
-			result.Y = Vector4.Dot(vec, mat.Column1);
-			result.Z = Vector4.Dot(vec, mat.Column2);
-			result.W = Vector4.Dot(vec, mat.Column3);
-			return result;
-		}
-
-		/// <summary>Transform a Vector by the given Matrix</summary>
-		/// <param name="vec">The vector to transform</param>
-		/// <param name="mat">The desired transformation</param>
-		/// <param name="result">The transformed vector</param>
-		public static void Transform(ref Vector4 vec, ref Matrix4 mat, out Vector4 result)
-		{
-			result.X = vec.X * mat.Row0.X +
-					   vec.Y * mat.Row1.X +
-					   vec.Z * mat.Row2.X +
-					   vec.W * mat.Row3.X;
-
-			result.Y = vec.X * mat.Row0.Y +
-					   vec.Y * mat.Row1.Y +
-					   vec.Z * mat.Row2.Y +
-					   vec.W * mat.Row3.Y;
-
-			result.Z = vec.X * mat.Row0.Z +
-					   vec.Y * mat.Row1.Z +
-					   vec.Z * mat.Row2.Z +
-					   vec.W * mat.Row3.Z;
-
-			result.W = vec.X * mat.Row0.W +
-					   vec.Y * mat.Row1.W +
-					   vec.Z * mat.Row2.W +
-					   vec.W * mat.Row3.W;
-		}
-
-		#endregion
-
-		#endregion
-
-		#region Swizzle
-
-		/// <summary>
-		/// Gets or sets an OpenTK.Vector2 with the X and Y components of this instance.
-		/// </summary>
-		
-		public Vector2 Xy { get { return new Vector2(X, Y); } set { X = value.X; Y = value.Y; } }
-
-		/// <summary>
-		/// Gets or sets an OpenTK.Vector3 with the X, Y and Z components of this instance.
-		/// </summary>
-		
-		public Vector3 Xyz { get { return new Vector3(X, Y, Z); } set { X = value.X; Y = value.Y; Z = value.Z; } }
-
-		#endregion
-
-		#region Operators
-
-		/// <summary>
-		/// Adds two instances.
-		/// </summary>
-		/// <param name="left">The first instance.</param>
-		/// <param name="right">The second instance.</param>
-		/// <returns>The result of the calculation.</returns>
-		public static Vector4 operator +(Vector4 left, Vector4 right)
-		{
-			left.X += right.X;
-			left.Y += right.Y;
-			left.Z += right.Z;
-			left.W += right.W;
-			return left;
-		}
-
-		/// <summary>
-		/// Subtracts two instances.
-		/// </summary>
-		/// <param name="left">The first instance.</param>
-		/// <param name="right">The second instance.</param>
-		/// <returns>The result of the calculation.</returns>
-		public static Vector4 operator -(Vector4 left, Vector4 right)
-		{
-			left.X -= right.X;
-			left.Y -= right.Y;
-			left.Z -= right.Z;
-			left.W -= right.W;
-			return left;
-		}
-
-		/// <summary>
-		/// Negates an instance.
-		/// </summary>
-		/// <param name="vec">The instance.</param>
-		/// <returns>The result of the calculation.</returns>
-		public static Vector4 operator -(Vector4 vec)
-		{
-			vec.X = -vec.X;
-			vec.Y = -vec.Y;
-			vec.Z = -vec.Z;
-			vec.W = -vec.W;
-			return vec;
-		}
-
-		/// <summary>
-		/// Multiplies an instance by a scalar.
-		/// </summary>
-		/// <param name="vec">The instance.</param>
-		/// <param name="scale">The scalar.</param>
-		/// <returns>The result of the calculation.</returns>
-		public static Vector4 operator *(Vector4 vec, float scale)
-		{
-			vec.X *= scale;
-			vec.Y *= scale;
-			vec.Z *= scale;
-			vec.W *= scale;
-			return vec;
-		}
-
-		/// <summary>
-		/// Multiplies an instance by a scalar.
-		/// </summary>
-		/// <param name="scale">The scalar.</param>
-		/// <param name="vec">The instance.</param>
-		/// <returns>The result of the calculation.</returns>
-		public static Vector4 operator *(float scale, Vector4 vec)
-		{
-			vec.X *= scale;
-			vec.Y *= scale;
-			vec.Z *= scale;
-			vec.W *= scale;
-			return vec;
-		}
-
-		/// <summary>
-		/// Divides an instance by a scalar.
-		/// </summary>
-		/// <param name="vec">The instance.</param>
-		/// <param name="scale">The scalar.</param>
-		/// <returns>The result of the calculation.</returns>
-		public static Vector4 operator /(Vector4 vec, float scale)
-		{
-			float mult = 1.0f / scale;
-			vec.X *= mult;
-			vec.Y *= mult;
-			vec.Z *= mult;
-			vec.W *= mult;
-			return vec;
-		}
-
-		/// <summary>
-		/// Compares two instances for equality.
-		/// </summary>
-		/// <param name="left">The first instance.</param>
-		/// <param name="right">The second instance.</param>
-		/// <returns>True, if left equals right; false otherwise.</returns>
-		public static bool operator ==(Vector4 left, Vector4 right)
-		{
-			return left.Equals(right);
-		}
-
-		/// <summary>
-		/// Compares two instances for inequality.
-		/// </summary>
-		/// <param name="left">The first instance.</param>
-		/// <param name="right">The second instance.</param>
-		/// <returns>True, if left does not equa lright; false otherwise.</returns>
-		public static bool operator !=(Vector4 left, Vector4 right)
-		{
-			return !left.Equals(right);
-		}
-
-		/// <summary>
-		/// Returns a pointer to the first element of the specified instance.
-		/// </summary>
-		/// <param name="v">The instance.</param>
-		/// <returns>A pointer to the first element of v.</returns>
-		[CLSCompliant(false)]
-		unsafe public static explicit operator float*(Vector4 v)
-		{
-			return &v.X;
-		}
-
-		/// <summary>
-		/// Returns a pointer to the first element of the specified instance.
-		/// </summary>
-		/// <param name="v">The instance.</param>
-		/// <returns>A pointer to the first element of v.</returns>
-		public static explicit operator IntPtr(Vector4 v)
-		{
-			unsafe
-			{
-				return (IntPtr)(&v.X);
-			}
-		}
-
-		#endregion
-
-		#region Overrides
-
-		#region public override string ToString()
-
-		/// <summary>
-		/// Returns a System.String that represents the current Vector4.
-		/// </summary>
-		/// <returns></returns>
-		public override string ToString()
-		{
-			return String.Format("({0}, {1}, {2}, {3})", X, Y, Z, W);
-		}
-
-		#endregion
-
-		#region public override int GetHashCode()
-
-		/// <summary>
-		/// Returns the hashcode for this instance.
-		/// </summary>
-		/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
-		public override int GetHashCode()
-		{
-			return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode() ^ W.GetHashCode();
-		}
-
-		#endregion
-
-		#region public override bool Equals(object obj)
-
-		/// <summary>
-		/// Indicates whether this instance and a specified object are equal.
-		/// </summary>
-		/// <param name="obj">The object to compare to.</param>
-		/// <returns>True if the instances are equal; false otherwise.</returns>
-		public override bool Equals(object obj)
-		{
-			if (!(obj is Vector4))
-				return false;
-
-			return this.Equals((Vector4)obj);
-		}
-
-		#endregion
-
-		#endregion
-
-		#endregion
-
-		#region IEquatable<Vector4> Members
-
-		/// <summary>Indicates whether the current vector is equal to another vector.</summary>
-		/// <param name="other">A vector to compare with this vector.</param>
-		/// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
-		public bool Equals(Vector4 other)
-		{
-			return
-				X == other.X &&
-				Y == other.Y &&
-				Z == other.Z &&
-				W == other.W;
-		}
-
-		#endregion
-	}
+    /// <summary>Represents a 4D vector using four single-precision floating-point numbers.</summary>
+    /// <remarks>
+    /// The Vector4 structure is suitable for interoperation with unmanaged code requiring four consecutive floats.
+    /// </remarks>
+    [StructLayout(LayoutKind.Sequential)]
+    public struct Vector4 : IEquatable<Vector4>
+    {
+        #region Fields
+
+        /// <summary>
+        /// The X component of the Vector4.
+        /// </summary>
+        public float X;
+
+        /// <summary>
+        /// The Y component of the Vector4.
+        /// </summary>
+        public float Y;
+
+        /// <summary>
+        /// The Z component of the Vector4.
+        /// </summary>
+        public float Z;
+
+        /// <summary>
+        /// The W component of the Vector4.
+        /// </summary>
+        public float W;
+
+        /// <summary>
+        /// Defines a unit-length Vector4 that points towards the X-axis.
+        /// </summary>
+        public static Vector4 UnitX = new Vector4(1, 0, 0, 0);
+
+        /// <summary>
+        /// Defines a unit-length Vector4 that points towards the Y-axis.
+        /// </summary>
+        public static Vector4 UnitY = new Vector4(0, 1, 0, 0);
+
+        /// <summary>
+        /// Defines a unit-length Vector4 that points towards the Z-axis.
+        /// </summary>
+        public static Vector4 UnitZ = new Vector4(0, 0, 1, 0);
+
+        /// <summary>
+        /// Defines a unit-length Vector4 that points towards the W-axis.
+        /// </summary>
+        public static Vector4 UnitW = new Vector4(0, 0, 0, 1);
+
+        /// <summary>
+        /// Defines a zero-length Vector4.
+        /// </summary>
+        public static Vector4 Zero = new Vector4(0, 0, 0, 0);
+
+        /// <summary>
+        /// Defines an instance with all components set to 1.
+        /// </summary>
+        public static readonly Vector4 One = new Vector4(1, 1, 1, 1);
+
+        /// <summary>
+        /// Defines the size of the Vector4 struct in bytes.
+        /// </summary>
+        public static readonly int SizeInBytes = Marshal.SizeOf(new Vector4());
+
+        #endregion
+
+        #region Constructors
+
+        /// <summary>
+        /// Constructs a new Vector4.
+        /// </summary>
+        /// <param name="x">The x component of the Vector4.</param>
+        /// <param name="y">The y component of the Vector4.</param>
+        /// <param name="z">The z component of the Vector4.</param>
+        /// <param name="w">The z component of the Vector4.</param>
+        public Vector4(float x, float y, float z, float w)
+        {
+            X = x;
+            Y = y;
+            Z = z;
+            W = w;
+        }
+
+        /// <summary>
+        /// Constructs a new Vector4 from the given Vector2.
+        /// </summary>
+        /// <param name="v">The Vector2 to copy components from.</param>
+        public Vector4(Vector2 v)
+        {
+            X = v.X;
+            Y = v.Y;
+            Z = 0.0f;
+            W = 0.0f;
+        }
+
+        /// <summary>
+        /// Constructs a new Vector4 from the given Vector3.
+        /// </summary>
+        /// <param name="v">The Vector3 to copy components from.</param>
+        public Vector4(Vector3 v)
+        {
+            X = v.X;
+            Y = v.Y;
+            Z = v.Z;
+            W = 0.0f;
+        }
+
+        /// <summary>
+        /// Constructs a new Vector4 from the specified Vector3 and W component.
+        /// </summary>
+        /// <param name="v">The Vector3 to copy components from.</param>
+        /// <param name="w">The W component of the new Vector4.</param>
+        public Vector4(Vector3 v, float w)
+        {
+            X = v.X;
+            Y = v.Y;
+            Z = v.Z;
+            W = w;
+        }
+
+        /// <summary>
+        /// Constructs a new Vector4 from the given Vector4.
+        /// </summary>
+        /// <param name="v">The Vector4 to copy components from.</param>
+        public Vector4(Vector4 v)
+        {
+            X = v.X;
+            Y = v.Y;
+            Z = v.Z;
+            W = v.W;
+        }
+
+        #endregion
+
+        #region Public Members
+
+        #region Instance
+
+        #region public void Add()
+
+        /// <summary>Add the Vector passed as parameter to this instance.</summary>
+        /// <param name="right">Right operand. This parameter is only read from.</param>
+        [Obsolete("Use static Add() method instead.")]
+        public void Add(Vector4 right)
+        {
+            this.X += right.X;
+            this.Y += right.Y;
+            this.Z += right.Z;
+            this.W += right.W;
+        }
+
+        /// <summary>Add the Vector passed as parameter to this instance.</summary>
+        /// <param name="right">Right operand. This parameter is only read from.</param>
+        [CLSCompliant(false)]
+        [Obsolete("Use static Add() method instead.")]
+        public void Add(ref Vector4 right)
+        {
+            this.X += right.X;
+            this.Y += right.Y;
+            this.Z += right.Z;
+            this.W += right.W;
+        }
+
+        #endregion public void Add()
+
+        #region public void Sub()
+
+        /// <summary>Subtract the Vector passed as parameter from this instance.</summary>
+        /// <param name="right">Right operand. This parameter is only read from.</param>
+        [Obsolete("Use static Subtract() method instead.")]
+        public void Sub(Vector4 right)
+        {
+            this.X -= right.X;
+            this.Y -= right.Y;
+            this.Z -= right.Z;
+            this.W -= right.W;
+        }
+
+        /// <summary>Subtract the Vector passed as parameter from this instance.</summary>
+        /// <param name="right">Right operand. This parameter is only read from.</param>
+        [CLSCompliant(false)]
+        [Obsolete("Use static Subtract() method instead.")]
+        public void Sub(ref Vector4 right)
+        {
+            this.X -= right.X;
+            this.Y -= right.Y;
+            this.Z -= right.Z;
+            this.W -= right.W;
+        }
+
+        #endregion public void Sub()
+
+        #region public void Mult()
+
+        /// <summary>Multiply this instance by a scalar.</summary>
+        /// <param name="f">Scalar operand.</param>
+        [Obsolete("Use static Multiply() method instead.")]
+        public void Mult(float f)
+        {
+            this.X *= f;
+            this.Y *= f;
+            this.Z *= f;
+            this.W *= f;
+        }
+
+        #endregion public void Mult()
+
+        #region public void Div()
+
+        /// <summary>Divide this instance by a scalar.</summary>
+        /// <param name="f">Scalar operand.</param>
+        [Obsolete("Use static Divide() method instead.")]
+        public void Div(float f)
+        {
+            float mult = 1.0f / f;
+            this.X *= mult;
+            this.Y *= mult;
+            this.Z *= mult;
+            this.W *= mult;
+        }
+
+        #endregion public void Div()
+
+        #region public float Length
+
+        /// <summary>
+        /// Gets the length (magnitude) of the vector.
+        /// </summary>
+        /// <see cref="LengthFast"/>
+        /// <seealso cref="LengthSquared"/>
+        public float Length
+        {
+            get
+            {
+                return (float)System.Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
+            }
+        }
+
+        #endregion
+
+        #region public float LengthFast
+
+        /// <summary>
+        /// Gets an approximation of the vector length (magnitude).
+        /// </summary>
+        /// <remarks>
+        /// This property uses an approximation of the square root function to calculate vector magnitude, with
+        /// an upper error bound of 0.001.
+        /// </remarks>
+        /// <see cref="Length"/>
+        /// <seealso cref="LengthSquared"/>
+        public float LengthFast
+        {
+            get
+            {
+                return 1.0f / MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z + W * W);
+            }
+        }
+
+        #endregion
+
+        #region public float LengthSquared
+
+        /// <summary>
+        /// Gets the square of the vector length (magnitude).
+        /// </summary>
+        /// <remarks>
+        /// This property avoids the costly square root operation required by the Length property. This makes it more suitable
+        /// for comparisons.
+        /// </remarks>
+        /// <see cref="Length"/>
+        /// <seealso cref="LengthFast"/>
+        public float LengthSquared
+        {
+            get
+            {
+                return X * X + Y * Y + Z * Z + W * W;
+            }
+        }
+
+        #endregion
+
+        #region public void Normalize()
+
+        /// <summary>
+        /// Scales the Vector4 to unit length.
+        /// </summary>
+        public void Normalize()
+        {
+            float scale = 1.0f / this.Length;
+            X *= scale;
+            Y *= scale;
+            Z *= scale;
+            W *= scale;
+        }
+
+        #endregion
+
+        #region public void NormalizeFast()
+
+        /// <summary>
+        /// Scales the Vector4 to approximately unit length.
+        /// </summary>
+        public void NormalizeFast()
+        {
+            float scale = MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z + W * W);
+            X *= scale;
+            Y *= scale;
+            Z *= scale;
+            W *= scale;
+        }
+
+        #endregion
+
+        #region public void Scale()
+
+        /// <summary>
+        /// Scales the current Vector4 by the given amounts.
+        /// </summary>
+        /// <param name="sx">The scale of the X component.</param>
+        /// <param name="sy">The scale of the Y component.</param>
+        /// <param name="sz">The scale of the Z component.</param>
+        /// <param name="sw">The scale of the Z component.</param>
+        [Obsolete("Use static Multiply() method instead.")]
+        public void Scale(float sx, float sy, float sz, float sw)
+        {
+            this.X = X * sx;
+            this.Y = Y * sy;
+            this.Z = Z * sz;
+            this.W = W * sw;
+        }
+
+        /// <summary>Scales this instance by the given parameter.</summary>
+        /// <param name="scale">The scaling of the individual components.</param>
+        [Obsolete("Use static Multiply() method instead.")]
+        public void Scale(Vector4 scale)
+        {
+            this.X *= scale.X;
+            this.Y *= scale.Y;
+            this.Z *= scale.Z;
+            this.W *= scale.W;
+        }
+
+        /// <summary>Scales this instance by the given parameter.</summary>
+        /// <param name="scale">The scaling of the individual components.</param>
+        [CLSCompliant(false)]
+        [Obsolete("Use static Multiply() method instead.")]
+        public void Scale(ref Vector4 scale)
+        {
+            this.X *= scale.X;
+            this.Y *= scale.Y;
+            this.Z *= scale.Z;
+            this.W *= scale.W;
+        }
+
+        #endregion public void Scale()
+
+        #endregion
+
+        #region Static
+
+        #region Obsolete
+
+        #region Sub
+
+        /// <summary>
+        /// Subtract one Vector from another
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <returns>Result of subtraction</returns>
+        public static Vector4 Sub(Vector4 a, Vector4 b)
+        {
+            a.X -= b.X;
+            a.Y -= b.Y;
+            a.Z -= b.Z;
+            a.W -= b.W;
+            return a;
+        }
+
+        /// <summary>
+        /// Subtract one Vector from another
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <param name="result">Result of subtraction</param>
+        public static void Sub(ref Vector4 a, ref Vector4 b, out Vector4 result)
+        {
+            result.X = a.X - b.X;
+            result.Y = a.Y - b.Y;
+            result.Z = a.Z - b.Z;
+            result.W = a.W - b.W;
+        }
+
+        #endregion
+
+        #region Mult
+
+        /// <summary>
+        /// Multiply a vector and a scalar
+        /// </summary>
+        /// <param name="a">Vector operand</param>
+        /// <param name="f">Scalar operand</param>
+        /// <returns>Result of the multiplication</returns>
+        public static Vector4 Mult(Vector4 a, float f)
+        {
+            a.X *= f;
+            a.Y *= f;
+            a.Z *= f;
+            a.W *= f;
+            return a;
+        }
+
+        /// <summary>
+        /// Multiply a vector and a scalar
+        /// </summary>
+        /// <param name="a">Vector operand</param>
+        /// <param name="f">Scalar operand</param>
+        /// <param name="result">Result of the multiplication</param>
+        public static void Mult(ref Vector4 a, float f, out Vector4 result)
+        {
+            result.X = a.X * f;
+            result.Y = a.Y * f;
+            result.Z = a.Z * f;
+            result.W = a.W * f;
+        }
+
+        #endregion
+
+        #region Div
+
+        /// <summary>
+        /// Divide a vector by a scalar
+        /// </summary>
+        /// <param name="a">Vector operand</param>
+        /// <param name="f">Scalar operand</param>
+        /// <returns>Result of the division</returns>
+        public static Vector4 Div(Vector4 a, float f)
+        {
+            float mult = 1.0f / f;
+            a.X *= mult;
+            a.Y *= mult;
+            a.Z *= mult;
+            a.W *= mult;
+            return a;
+        }
+
+        /// <summary>
+        /// Divide a vector by a scalar
+        /// </summary>
+        /// <param name="a">Vector operand</param>
+        /// <param name="f">Scalar operand</param>
+        /// <param name="result">Result of the division</param>
+        public static void Div(ref Vector4 a, float f, out Vector4 result)
+        {
+            float mult = 1.0f / f;
+            result.X = a.X * mult;
+            result.Y = a.Y * mult;
+            result.Z = a.Z * mult;
+            result.W = a.W * mult;
+        }
+
+        #endregion
+
+        #endregion
+
+        #region Add
+
+        /// <summary>
+        /// Adds two vectors.
+        /// </summary>
+        /// <param name="a">Left operand.</param>
+        /// <param name="b">Right operand.</param>
+        /// <returns>Result of operation.</returns>
+        public static Vector4 Add(Vector4 a, Vector4 b)
+        {
+            Add(ref a, ref b, out a);
+            return a;
+        }
+
+        /// <summary>
+        /// Adds two vectors.
+        /// </summary>
+        /// <param name="a">Left operand.</param>
+        /// <param name="b">Right operand.</param>
+        /// <param name="result">Result of operation.</param>
+        public static void Add(ref Vector4 a, ref Vector4 b, out Vector4 result)
+        {
+            result = new Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W);
+        }
+
+        #endregion
+
+        #region Subtract
+
+        /// <summary>
+        /// Subtract one Vector from another
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <returns>Result of subtraction</returns>
+        public static Vector4 Subtract(Vector4 a, Vector4 b)
+        {
+            Subtract(ref a, ref b, out a);
+            return a;
+        }
+
+        /// <summary>
+        /// Subtract one Vector from another
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <param name="result">Result of subtraction</param>
+        public static void Subtract(ref Vector4 a, ref Vector4 b, out Vector4 result)
+        {
+            result = new Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W);
+        }
+
+        #endregion
+
+        #region Multiply
+
+        /// <summary>
+        /// Multiplies a vector by a scalar.
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of the operation.</returns>
+        public static Vector4 Multiply(Vector4 vector, float scale)
+        {
+            Multiply(ref vector, scale, out vector);
+            return vector;
+        }
+
+        /// <summary>
+        /// Multiplies a vector by a scalar.
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <param name="result">Result of the operation.</param>
+        public static void Multiply(ref Vector4 vector, float scale, out Vector4 result)
+        {
+            result = new Vector4(vector.X * scale, vector.Y * scale, vector.Z * scale, vector.W * scale);
+        }
+
+        /// <summary>
+        /// Multiplies a vector by the components a vector (scale).
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of the operation.</returns>
+        public static Vector4 Multiply(Vector4 vector, Vector4 scale)
+        {
+            Multiply(ref vector, ref scale, out vector);
+            return vector;
+        }
+
+        /// <summary>
+        /// Multiplies a vector by the components of a vector (scale).
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <param name="result">Result of the operation.</param>
+        public static void Multiply(ref Vector4 vector, ref Vector4 scale, out Vector4 result)
+        {
+            result = new Vector4(vector.X * scale.X, vector.Y * scale.Y, vector.Z * scale.Z, vector.W * scale.W);
+        }
+
+        #endregion
+
+        #region Divide
+
+        /// <summary>
+        /// Divides a vector by a scalar.
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of the operation.</returns>
+        public static Vector4 Divide(Vector4 vector, float scale)
+        {
+            Divide(ref vector, scale, out vector);
+            return vector;
+        }
+
+        /// <summary>
+        /// Divides a vector by a scalar.
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <param name="result">Result of the operation.</param>
+        public static void Divide(ref Vector4 vector, float scale, out Vector4 result)
+        {
+            Multiply(ref vector, 1 / scale, out result);
+        }
+
+        /// <summary>
+        /// Divides a vector by the components of a vector (scale).
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <returns>Result of the operation.</returns>
+        public static Vector4 Divide(Vector4 vector, Vector4 scale)
+        {
+            Divide(ref vector, ref scale, out vector);
+            return vector;
+        }
+
+        /// <summary>
+        /// Divide a vector by the components of a vector (scale).
+        /// </summary>
+        /// <param name="vector">Left operand.</param>
+        /// <param name="scale">Right operand.</param>
+        /// <param name="result">Result of the operation.</param>
+        public static void Divide(ref Vector4 vector, ref Vector4 scale, out Vector4 result)
+        {
+            result = new Vector4(vector.X / scale.X, vector.Y / scale.Y, vector.Z / scale.Z, vector.W / scale.W);
+        }
+
+        #endregion
+
+        #region Min
+
+        /// <summary>
+        /// Calculate the component-wise minimum of two vectors
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <returns>The component-wise minimum</returns>
+        public static Vector4 Min(Vector4 a, Vector4 b)
+        {
+            a.X = a.X < b.X ? a.X : b.X;
+            a.Y = a.Y < b.Y ? a.Y : b.Y;
+            a.Z = a.Z < b.Z ? a.Z : b.Z;
+            a.W = a.W < b.W ? a.W : b.W;
+            return a;
+        }
+
+        /// <summary>
+        /// Calculate the component-wise minimum of two vectors
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <param name="result">The component-wise minimum</param>
+        public static void Min(ref Vector4 a, ref Vector4 b, out Vector4 result)
+        {
+            result.X = a.X < b.X ? a.X : b.X;
+            result.Y = a.Y < b.Y ? a.Y : b.Y;
+            result.Z = a.Z < b.Z ? a.Z : b.Z;
+            result.W = a.W < b.W ? a.W : b.W;
+        }
+
+        #endregion
+
+        #region Max
+
+        /// <summary>
+        /// Calculate the component-wise maximum of two vectors
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <returns>The component-wise maximum</returns>
+        public static Vector4 Max(Vector4 a, Vector4 b)
+        {
+            a.X = a.X > b.X ? a.X : b.X;
+            a.Y = a.Y > b.Y ? a.Y : b.Y;
+            a.Z = a.Z > b.Z ? a.Z : b.Z;
+            a.W = a.W > b.W ? a.W : b.W;
+            return a;
+        }
+
+        /// <summary>
+        /// Calculate the component-wise maximum of two vectors
+        /// </summary>
+        /// <param name="a">First operand</param>
+        /// <param name="b">Second operand</param>
+        /// <param name="result">The component-wise maximum</param>
+        public static void Max(ref Vector4 a, ref Vector4 b, out Vector4 result)
+        {
+            result.X = a.X > b.X ? a.X : b.X;
+            result.Y = a.Y > b.Y ? a.Y : b.Y;
+            result.Z = a.Z > b.Z ? a.Z : b.Z;
+            result.W = a.W > b.W ? a.W : b.W;
+        }
+
+        #endregion
+
+        #region Clamp
+
+        /// <summary>
+        /// Clamp a vector to the given minimum and maximum vectors
+        /// </summary>
+        /// <param name="vec">Input vector</param>
+        /// <param name="min">Minimum vector</param>
+        /// <param name="max">Maximum vector</param>
+        /// <returns>The clamped vector</returns>
+        public static Vector4 Clamp(Vector4 vec, Vector4 min, Vector4 max)
+        {
+            vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
+            vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
+            vec.Z = vec.X < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
+            vec.W = vec.Y < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
+            return vec;
+        }
+
+        /// <summary>
+        /// Clamp a vector to the given minimum and maximum vectors
+        /// </summary>
+        /// <param name="vec">Input vector</param>
+        /// <param name="min">Minimum vector</param>
+        /// <param name="max">Maximum vector</param>
+        /// <param name="result">The clamped vector</param>
+        public static void Clamp(ref Vector4 vec, ref Vector4 min, ref Vector4 max, out Vector4 result)
+        {
+            result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
+            result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
+            result.Z = vec.X < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
+            result.W = vec.Y < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
+        }
+
+        #endregion
+
+        #region Normalize
+
+        /// <summary>
+        /// Scale a vector to unit length
+        /// </summary>
+        /// <param name="vec">The input vector</param>
+        /// <returns>The normalized vector</returns>
+        public static Vector4 Normalize(Vector4 vec)
+        {
+            float scale = 1.0f / vec.Length;
+            vec.X *= scale;
+            vec.Y *= scale;
+            vec.Z *= scale;
+            vec.W *= scale;
+            return vec;
+        }
+
+        /// <summary>
+        /// Scale a vector to unit length
+        /// </summary>
+        /// <param name="vec">The input vector</param>
+        /// <param name="result">The normalized vector</param>
+        public static void Normalize(ref Vector4 vec, out Vector4 result)
+        {
+            float scale = 1.0f / vec.Length;
+            result.X = vec.X * scale;
+            result.Y = vec.Y * scale;
+            result.Z = vec.Z * scale;
+            result.W = vec.W * scale;
+        }
+
+        #endregion
+
+        #region NormalizeFast
+
+        /// <summary>
+        /// Scale a vector to approximately unit length
+        /// </summary>
+        /// <param name="vec">The input vector</param>
+        /// <returns>The normalized vector</returns>
+        public static Vector4 NormalizeFast(Vector4 vec)
+        {
+            float scale = MathHelper.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y + vec.Z * vec.Z + vec.W * vec.W);
+            vec.X *= scale;
+            vec.Y *= scale;
+            vec.Z *= scale;
+            vec.W *= scale;
+            return vec;
+        }
+
+        /// <summary>
+        /// Scale a vector to approximately unit length
+        /// </summary>
+        /// <param name="vec">The input vector</param>
+        /// <param name="result">The normalized vector</param>
+        public static void NormalizeFast(ref Vector4 vec, out Vector4 result)
+        {
+            float scale = MathHelper.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y + vec.Z * vec.Z + vec.W * vec.W);
+            result.X = vec.X * scale;
+            result.Y = vec.Y * scale;
+            result.Z = vec.Z * scale;
+            result.W = vec.W * scale;
+        }
+
+        #endregion
+
+        #region Dot
+
+        /// <summary>
+        /// Calculate the dot product of two vectors
+        /// </summary>
+        /// <param name="left">First operand</param>
+        /// <param name="right">Second operand</param>
+        /// <returns>The dot product of the two inputs</returns>
+        public static float Dot(Vector4 left, Vector4 right)
+        {
+            return left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
+        }
+
+        /// <summary>
+        /// Calculate the dot product of two vectors
+        /// </summary>
+        /// <param name="left">First operand</param>
+        /// <param name="right">Second operand</param>
+        /// <param name="result">The dot product of the two inputs</param>
+        public static void Dot(ref Vector4 left, ref Vector4 right, out float result)
+        {
+            result = left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
+        }
+
+        #endregion
+
+        #region Lerp
+
+        /// <summary>
+        /// Returns a new Vector that is the linear blend of the 2 given Vectors
+        /// </summary>
+        /// <param name="a">First input vector</param>
+        /// <param name="b">Second input vector</param>
+        /// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
+        /// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
+        public static Vector4 Lerp(Vector4 a, Vector4 b, float blend)
+        {
+            a.X = blend * (b.X - a.X) + a.X;
+            a.Y = blend * (b.Y - a.Y) + a.Y;
+            a.Z = blend * (b.Z - a.Z) + a.Z;
+            a.W = blend * (b.W - a.W) + a.W;
+            return a;
+        }
+
+        /// <summary>
+        /// Returns a new Vector that is the linear blend of the 2 given Vectors
+        /// </summary>
+        /// <param name="a">First input vector</param>
+        /// <param name="b">Second input vector</param>
+        /// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
+        /// <param name="result">a when blend=0, b when blend=1, and a linear combination otherwise</param>
+        public static void Lerp(ref Vector4 a, ref Vector4 b, float blend, out Vector4 result)
+        {
+            result.X = blend * (b.X - a.X) + a.X;
+            result.Y = blend * (b.Y - a.Y) + a.Y;
+            result.Z = blend * (b.Z - a.Z) + a.Z;
+            result.W = blend * (b.W - a.W) + a.W;
+        }
+
+        #endregion
+
+        #region Barycentric
+
+        /// <summary>
+        /// Interpolate 3 Vectors using Barycentric coordinates
+        /// </summary>
+        /// <param name="a">First input Vector</param>
+        /// <param name="b">Second input Vector</param>
+        /// <param name="c">Third input Vector</param>
+        /// <param name="u">First Barycentric Coordinate</param>
+        /// <param name="v">Second Barycentric Coordinate</param>
+        /// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
+        public static Vector4 BaryCentric(Vector4 a, Vector4 b, Vector4 c, float u, float v)
+        {
+            return a + u * (b - a) + v * (c - a);
+        }
+
+        /// <summary>Interpolate 3 Vectors using Barycentric coordinates</summary>
+        /// <param name="a">First input Vector.</param>
+        /// <param name="b">Second input Vector.</param>
+        /// <param name="c">Third input Vector.</param>
+        /// <param name="u">First Barycentric Coordinate.</param>
+        /// <param name="v">Second Barycentric Coordinate.</param>
+        /// <param name="result">Output Vector. a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</param>
+        public static void BaryCentric(ref Vector4 a, ref Vector4 b, ref Vector4 c, float u, float v, out Vector4 result)
+        {
+            result = a; // copy
+
+            Vector4 temp = b; // copy
+            Subtract(ref temp, ref a, out temp);
+            Multiply(ref temp, u, out temp);
+            Add(ref result, ref temp, out result);
+
+            temp = c; // copy
+            Subtract(ref temp, ref a, out temp);
+            Multiply(ref temp, v, out temp);
+            Add(ref result, ref temp, out result);
+        }
+
+        #endregion
+
+        #region Transform
+
+        /// <summary>Transform a Vector by the given Matrix</summary>
+        /// <param name="vec">The vector to transform</param>
+        /// <param name="mat">The desired transformation</param>
+        /// <returns>The transformed vector</returns>
+        public static Vector4 Transform(Vector4 vec, Matrix4 mat)
+        {
+            Vector4 result;
+            result.X = Vector4.Dot(vec, mat.Column0);
+            result.Y = Vector4.Dot(vec, mat.Column1);
+            result.Z = Vector4.Dot(vec, mat.Column2);
+            result.W = Vector4.Dot(vec, mat.Column3);
+            return result;
+        }
+
+        /// <summary>Transform a Vector by the given Matrix</summary>
+        /// <param name="vec">The vector to transform</param>
+        /// <param name="mat">The desired transformation</param>
+        /// <param name="result">The transformed vector</param>
+        public static void Transform(ref Vector4 vec, ref Matrix4 mat, out Vector4 result)
+        {
+            result.X = vec.X * mat.Row0.X +
+                       vec.Y * mat.Row1.X +
+                       vec.Z * mat.Row2.X +
+                       vec.W * mat.Row3.X;
+
+            result.Y = vec.X * mat.Row0.Y +
+                       vec.Y * mat.Row1.Y +
+                       vec.Z * mat.Row2.Y +
+                       vec.W * mat.Row3.Y;
+
+            result.Z = vec.X * mat.Row0.Z +
+                       vec.Y * mat.Row1.Z +
+                       vec.Z * mat.Row2.Z +
+                       vec.W * mat.Row3.Z;
+
+            result.W = vec.X * mat.Row0.W +
+                       vec.Y * mat.Row1.W +
+                       vec.Z * mat.Row2.W +
+                       vec.W * mat.Row3.W;
+        }
+
+        #endregion
+
+        #endregion
+
+        #region Swizzle
+
+        /// <summary>
+        /// Gets or sets an OpenTK.Vector2 with the X and Y components of this instance.
+        /// </summary>
+        
+        public Vector2 Xy { get { return new Vector2(X, Y); } set { X = value.X; Y = value.Y; } }
+
+        /// <summary>
+        /// Gets or sets an OpenTK.Vector3 with the X, Y and Z components of this instance.
+        /// </summary>
+        
+        public Vector3 Xyz { get { return new Vector3(X, Y, Z); } set { X = value.X; Y = value.Y; Z = value.Z; } }
+
+        #endregion
+
+        #region Operators
+
+        /// <summary>
+        /// Adds two instances.
+        /// </summary>
+        /// <param name="left">The first instance.</param>
+        /// <param name="right">The second instance.</param>
+        /// <returns>The result of the calculation.</returns>
+        public static Vector4 operator +(Vector4 left, Vector4 right)
+        {
+            left.X += right.X;
+            left.Y += right.Y;
+            left.Z += right.Z;
+            left.W += right.W;
+            return left;
+        }
+
+        /// <summary>
+        /// Subtracts two instances.
+        /// </summary>
+        /// <param name="left">The first instance.</param>
+        /// <param name="right">The second instance.</param>
+        /// <returns>The result of the calculation.</returns>
+        public static Vector4 operator -(Vector4 left, Vector4 right)
+        {
+            left.X -= right.X;
+            left.Y -= right.Y;
+            left.Z -= right.Z;
+            left.W -= right.W;
+            return left;
+        }
+
+        /// <summary>
+        /// Negates an instance.
+        /// </summary>
+        /// <param name="vec">The instance.</param>
+        /// <returns>The result of the calculation.</returns>
+        public static Vector4 operator -(Vector4 vec)
+        {
+            vec.X = -vec.X;
+            vec.Y = -vec.Y;
+            vec.Z = -vec.Z;
+            vec.W = -vec.W;
+            return vec;
+        }
+
+        /// <summary>
+        /// Multiplies an instance by a scalar.
+        /// </summary>
+        /// <param name="vec">The instance.</param>
+        /// <param name="scale">The scalar.</param>
+        /// <returns>The result of the calculation.</returns>
+        public static Vector4 operator *(Vector4 vec, float scale)
+        {
+            vec.X *= scale;
+            vec.Y *= scale;
+            vec.Z *= scale;
+            vec.W *= scale;
+            return vec;
+        }
+
+        /// <summary>
+        /// Multiplies an instance by a scalar.
+        /// </summary>
+        /// <param name="scale">The scalar.</param>
+        /// <param name="vec">The instance.</param>
+        /// <returns>The result of the calculation.</returns>
+        public static Vector4 operator *(float scale, Vector4 vec)
+        {
+            vec.X *= scale;
+            vec.Y *= scale;
+            vec.Z *= scale;
+            vec.W *= scale;
+            return vec;
+        }
+
+        /// <summary>
+        /// Divides an instance by a scalar.
+        /// </summary>
+        /// <param name="vec">The instance.</param>
+        /// <param name="scale">The scalar.</param>
+        /// <returns>The result of the calculation.</returns>
+        public static Vector4 operator /(Vector4 vec, float scale)
+        {
+            float mult = 1.0f / scale;
+            vec.X *= mult;
+            vec.Y *= mult;
+            vec.Z *= mult;
+            vec.W *= mult;
+            return vec;
+        }
+
+        /// <summary>
+        /// Compares two instances for equality.
+        /// </summary>
+        /// <param name="left">The first instance.</param>
+        /// <param name="right">The second instance.</param>
+        /// <returns>True, if left equals right; false otherwise.</returns>
+        public static bool operator ==(Vector4 left, Vector4 right)
+        {
+            return left.Equals(right);
+        }
+
+        /// <summary>
+        /// Compares two instances for inequality.
+        /// </summary>
+        /// <param name="left">The first instance.</param>
+        /// <param name="right">The second instance.</param>
+        /// <returns>True, if left does not equa lright; false otherwise.</returns>
+        public static bool operator !=(Vector4 left, Vector4 right)
+        {
+            return !left.Equals(right);
+        }
+
+        /// <summary>
+        /// Returns a pointer to the first element of the specified instance.
+        /// </summary>
+        /// <param name="v">The instance.</param>
+        /// <returns>A pointer to the first element of v.</returns>
+        [CLSCompliant(false)]
+        unsafe public static explicit operator float*(Vector4 v)
+        {
+            return &v.X;
+        }
+
+        /// <summary>
+        /// Returns a pointer to the first element of the specified instance.
+        /// </summary>
+        /// <param name="v">The instance.</param>
+        /// <returns>A pointer to the first element of v.</returns>
+        public static explicit operator IntPtr(Vector4 v)
+        {
+            unsafe
+            {
+                return (IntPtr)(&v.X);
+            }
+        }
+
+        #endregion
+
+        #region Overrides
+
+        #region public override string ToString()
+
+        /// <summary>
+        /// Returns a System.String that represents the current Vector4.
+        /// </summary>
+        /// <returns></returns>
+        public override string ToString()
+        {
+            return String.Format("({0}, {1}, {2}, {3})", X, Y, Z, W);
+        }
+
+        #endregion
+
+        #region public override int GetHashCode()
+
+        /// <summary>
+        /// Returns the hashcode for this instance.
+        /// </summary>
+        /// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
+        public override int GetHashCode()
+        {
+            return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode() ^ W.GetHashCode();
+        }
+
+        #endregion
+
+        #region public override bool Equals(object obj)
+
+        /// <summary>
+        /// Indicates whether this instance and a specified object are equal.
+        /// </summary>
+        /// <param name="obj">The object to compare to.</param>
+        /// <returns>True if the instances are equal; false otherwise.</returns>
+        public override bool Equals(object obj)
+        {
+            if (!(obj is Vector4))
+                return false;
+
+            return this.Equals((Vector4)obj);
+        }
+
+        #endregion
+
+        #endregion
+
+        #endregion
+
+        #region IEquatable<Vector4> Members
+
+        /// <summary>Indicates whether the current vector is equal to another vector.</summary>
+        /// <param name="other">A vector to compare with this vector.</param>
+        /// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
+        public bool Equals(Vector4 other)
+        {
+            return
+                X == other.X &&
+                Y == other.Y &&
+                Z == other.Z &&
+                W == other.W;
+        }
+
+        #endregion
+    }
 }

+ 26 - 0
Script/AtomicNET/AtomicNETProject.json

@@ -101,6 +101,32 @@
                 "$ATOMIC_ROOT$/Script/AtomicNET/Platform/Android/"
             ]
         },
+        {
+            "name": "AtomicNET.iOS",
+            "platforms" : ["ios"],
+            "outputType" : "Library",
+            "projectTypeGuids" :[ "8FFB629D-F513-41CE-95D2-7ECE97B6EEEC", "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC" ],
+            "defineConstants" : ["ATOMIC_IOS"],
+            "rootNamespace" : "AtomicGameEngine",
+            "assemblyName" : "AtomicNET",
+            "assemblyOutputPath" : "..\\..\\$ATOMIC_CONFIG$\\iOS\\",
+            "projectGuid" : "C74AB5E8-7517-11E6-AE3F-005056C00008",
+            "objcBindingApiDefinition" : "$ATOMIC_ROOT$/Script/AtomicNET/Platform/iOS/ApiDefinition/ApiDefinition.cs",
+            "references" : [
+                "Xamarin.iOS",
+                "System",
+                "System.Core",
+                "System.Xml.Linq",
+                "System.Xml"
+            ],
+            "sharedReferences" : [
+                "AtomicNET.Shared"
+            ],
+            "sources" : [
+                "$ATOMIC_ROOT$/Script/AtomicNET/Platform/iOS/AtomicNET"
+            ],
+            "importProjects" : ["$(MSBuildExtensionsPath)\\Xamarin\\iOS\\Xamarin.iOS.ObjCBinding.CSharp.targets"]
+        },
         {
             "name": "AtomicNETService",
             "platforms" : ["desktop"],

+ 14 - 14
Script/AtomicNET/AtomicNETService/AtomicTools.cs

@@ -16,26 +16,26 @@ using File = System.IO.File;
 
 namespace AtomicTools
 {
-	public class AtomicTools
-	{
+    public class AtomicTools
+    {
 
-		public static String InspectAssembly (String pathToAssembly)
-		{
+        public static String InspectAssembly (String pathToAssembly)
+        {
 
-			try {
+            try {
 
-				var inspector = new AssemblyInspector ();
-				inspector.Inspect (pathToAssembly);
-				return inspector.DumpToJSON();
+                var inspector = new AssemblyInspector ();
+                inspector.Inspect (pathToAssembly);
+                return inspector.DumpToJSON();
 
-			} catch (Exception ex) {
-				Console.WriteLine (ex.Message);
-			}
+            } catch (Exception ex) {
+                Console.WriteLine (ex.Message);
+            }
 
-			return "";
+            return "";
 
-		}
+        }
 
-	}
+    }
 
 }

+ 17 - 17
Script/AtomicNET/AtomicNETService/CSComponentInspector.cs

@@ -824,23 +824,23 @@ namespace AtomicTools
         public void Dump()
         {
             /*
-				foreach (var entry in InspectorFields) {
-					var field = entry.Value;
-
-					Console.WriteLine ("Inspector Field: {0}", field.Name);
-
-					Console.WriteLine ("   Type Name: {0}", field.TypeName);
-					Console.WriteLine ("   Default Value: {0}", field.DefaultValue);
-
-					Console.WriteLine ("   Positional Custom Attr:");
-					foreach (var p in field.CustomAttrPositionalArgs)
-					if (p.Length != 0)
-					Console.WriteLine ("      {0}", p);
-					Console.WriteLine ("   Named Custom Attr:");
-					foreach (var nentry in field.CustomAttrNamedArgs)
-					Console.WriteLine ("      {0}:{1}", nentry.Key, nentry.Value);
-				}
-				*/
+                foreach (var entry in InspectorFields) {
+                    var field = entry.Value;
+
+                    Console.WriteLine ("Inspector Field: {0}", field.Name);
+
+                    Console.WriteLine ("   Type Name: {0}", field.TypeName);
+                    Console.WriteLine ("   Default Value: {0}", field.DefaultValue);
+
+                    Console.WriteLine ("   Positional Custom Attr:");
+                    foreach (var p in field.CustomAttrPositionalArgs)
+                    if (p.Length != 0)
+                    Console.WriteLine ("      {0}", p);
+                    Console.WriteLine ("   Named Custom Attr:");
+                    foreach (var nentry in field.CustomAttrNamedArgs)
+                    Console.WriteLine ("      {0}:{1}", nentry.Key, nentry.Value);
+                }
+                */
         }
 
     }

+ 0 - 7
Script/AtomicNET/AtomicNETService/Program.cs

@@ -1,11 +1,6 @@
 using System;
 using AtomicEngine;
 
-// net genproject C:\Dev\atomic\AtomicGameEngine\Script\AtomicNET\AtomicNETProject.json WINDOWS
-// net parse C:\Dev\atomic\AtomicGameEngine\Artifacts\AtomicNET\Build\AtomicNETService\bin\Debug\AtomicNETService.exe
-// net compile C:\Dev\atomic\AtomicGameEngine\Artifacts\AtomicNET\Build\AtomicNET.sln
-
-
 namespace AtomicTools
 {
 
@@ -68,5 +63,3 @@ namespace AtomicTools
         }
     }
 }
-
-

+ 40 - 40
Script/AtomicNET/AtomicPlayer/AtomicPlayer.Android/MainActivity.cs

@@ -9,56 +9,56 @@ using AtomicBlaster;
 
 namespace AtomicPlayer
 {
-	[Activity(Label = "AtomicPlayer", MainLauncher = true,
-		Icon = "@drawable/icon", Theme = "@android:style/Theme.NoTitleBar.Fullscreen",
-		ConfigurationChanges = ConfigChanges.KeyboardHidden | ConfigChanges.Orientation,
-		ScreenOrientation = ScreenOrientation.Landscape)]
-	public class MainActivity : Activity
-	{
-		protected override void OnCreate(Bundle bundle)
-		{
-			base.OnCreate(bundle);
-			var mLayout = new AbsoluteLayout(this);
+    [Activity(Label = "AtomicPlayer", MainLauncher = true,
+        Icon = "@drawable/icon", Theme = "@android:style/Theme.NoTitleBar.Fullscreen",
+        ConfigurationChanges = ConfigChanges.KeyboardHidden | ConfigChanges.Orientation,
+        ScreenOrientation = ScreenOrientation.Landscape)]
+    public class MainActivity : Activity
+    {
+        protected override void OnCreate(Bundle bundle)
+        {
+            base.OnCreate(bundle);
+            var mLayout = new AbsoluteLayout(this);
             var surface = AndroidSDLSurface.CreateSurface(this, false, typeof(GameRoot));
-			mLayout.AddView(surface);
-			SetContentView(mLayout);
-		}
+            mLayout.AddView(surface);
+            SetContentView(mLayout);
+        }
 
-		protected override void OnResume()
-		{
+        protected override void OnResume()
+        {
             AndroidSDLSurface.OnResume();
-			base.OnResume();
-		}
+            base.OnResume();
+        }
 
-		protected override void OnPause()
-		{
+        protected override void OnPause()
+        {
             AndroidSDLSurface.OnPause();
-			base.OnPause();
-		}
+            base.OnPause();
+        }
 
-		public override void OnLowMemory()
-		{
+        public override void OnLowMemory()
+        {
             AndroidSDLSurface.OnLowMemory();
-			base.OnLowMemory();
-		}
+            base.OnLowMemory();
+        }
 
-		protected override void OnDestroy()
-		{
+        protected override void OnDestroy()
+        {
             AndroidSDLSurface.OnDestroy();
-			base.OnDestroy();
-		}
+            base.OnDestroy();
+        }
 
-		public override bool DispatchKeyEvent(KeyEvent e)
-		{
-			if (!AndroidSDLSurface.DispatchKeyEvent(e))
-				return false;
-			return base.DispatchKeyEvent(e);
-		}
+        public override bool DispatchKeyEvent(KeyEvent e)
+        {
+            if (!AndroidSDLSurface.DispatchKeyEvent(e))
+                return false;
+            return base.DispatchKeyEvent(e);
+        }
 
-		public override void OnWindowFocusChanged(bool hasFocus)
-		{
+        public override void OnWindowFocusChanged(bool hasFocus)
+        {
             AndroidSDLSurface.OnWindowFocusChanged(hasFocus);
-			base.OnWindowFocusChanged(hasFocus);
-		}
-	}
+            base.OnWindowFocusChanged(hasFocus);
+        }
+    }
 }

+ 31 - 0
Script/AtomicNET/AtomicProject.json

@@ -84,6 +84,37 @@
                 "$ATOMIC_ROOT$/Script/AtomicNET/AtomicPlayer/AtomicPlayer.Common",
                 "$ATOMIC_PROJECT_ROOT$/Project/AtomicNET/Platforms/Android"
             ]
+        },
+        {
+            "name": "$ATOMIC_PROJECT_NAME$.iOS",
+            "platforms" : ["ios"],
+            "outputType" : "Exe",
+            "defineConstants" : ["ATOMIC_IOS"],
+            "rootNamespace" : "",
+            "assemblyName" : "$ATOMIC_PROJECT_NAME$",
+            "projectGuid" : "071BD84E-7518-11E6-C78E-005056C00008",
+            "projectTypeGuids" : ["FEACFBD2-3405-455C-9665-78FE426C6842", "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC"],
+            "assemblyOutputPath" : "$ATOMIC_PROJECT_ROOT$\\AtomicNET\\$ATOMIC_CONFIG$\\Bin\\iOS",
+            "playerApplication" : true,
+            "codesignEntitlements" : "$ATOMIC_PROJECT_ROOT$/Project/AtomicNET/Platforms/iOS/Entitlements.plist",
+            "infoPList" : "$ATOMIC_PROJECT_ROOT$/Project/AtomicNET/Platforms/iOS/Info.plist",
+            "references" : [
+                "Xamarin.iOS",
+                "System",
+                "System.Core",
+                "System.Xml.Linq",
+                "System.Xml",
+                "AtomicNET.iOS"
+            ],
+            "sharedReferences" : [
+                "$ATOMIC_PROJECT_NAME$.Shared"
+            ],
+            "sources" : [
+                "$ATOMIC_ROOT$/Script/AtomicNET/AtomicPlayer/AtomicPlayer.Common",
+                "$ATOMIC_PROJECT_ROOT$/Project/AtomicNET/Platforms/iOS"
+            ],
+            "importProjects" : ["$(MSBuildExtensionsPath)\\Xamarin\\iOS\\Xamarin.iOS.CSharp.targets"]
         }
+
     ]
 }

+ 10 - 0
Script/AtomicNET/Platform/iOS/ApiDefinition/ApiDefinition.cs

@@ -0,0 +1,10 @@
+using System;
+
+using UIKit;
+using Foundation;
+using ObjCRuntime;
+using CoreGraphics;
+
+namespace AtomicGameEngine
+{
+}

+ 3 - 0
Script/AtomicNET/Platform/iOS/AtomicNET/AtomicNETNative.framework.linkwith.cs

@@ -0,0 +1,3 @@
+using ObjCRuntime;
+
+[assembly: LinkWith ("AtomicNETNative.framework")]

+ 1 - 1
Source/Atomic/Graphics/Direct3D11/D3D11Graphics.cpp

@@ -239,7 +239,7 @@ Graphics::Graphics(Context* context) :
 
     // Initialize SDL now. Graphics should be the first SDL-using subsystem to be created
     SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE
-		| SDL_INIT_TIMER | SDL_INIT_HAPTIC ); // ATOMIC BEGIN  HAPTIC  //ATOMIC END
+        | SDL_INIT_TIMER | SDL_INIT_HAPTIC ); // ATOMIC BEGIN  HAPTIC  //ATOMIC END
 
     // Register Graphics library object factories
     RegisterGraphicsLibrary(context_);

+ 1 - 1
Source/Atomic/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -281,7 +281,7 @@ Graphics::Graphics(Context* context) :
 
     // Initialize SDL now. Graphics should be the first SDL-using subsystem to be created
     SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE
-		| SDL_INIT_TIMER | SDL_INIT_HAPTIC );  // ATOMIC BEGIN  HAPTIC  //ATOMIC END
+        | SDL_INIT_TIMER | SDL_INIT_HAPTIC );  // ATOMIC BEGIN  HAPTIC  //ATOMIC END
 
     // Register Graphics library object factories
     RegisterGraphicsLibrary(context_);

+ 1 - 1
Source/Atomic/Graphics/OpenGL/OGLGraphics.cpp

@@ -269,7 +269,7 @@ Graphics::Graphics(Context* context_) :
 
     // Initialize SDL now. Graphics should be the first SDL-using subsystem to be created
     SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE
-		| SDL_INIT_TIMER | SDL_INIT_HAPTIC );  // ATOMIC BEGIN  HAPTIC  //ATOMIC END
+        | SDL_INIT_TIMER | SDL_INIT_HAPTIC );  // ATOMIC BEGIN  HAPTIC  //ATOMIC END
 
     // Register Graphics library object factories
     RegisterGraphicsLibrary(context_);

+ 9 - 9
Source/Atomic/IPC/IPCWorker.cpp

@@ -40,16 +40,16 @@ namespace Atomic
 IPCWorker::IPCWorker(Context* context, IPCHandle clientRead, IPCHandle clientWrite, unsigned id) : IPCChannel(context, id)
 {
 #ifndef ATOMIC_PLATFORM_WINDOWS
-	assert(0); // wrong constructor
+    assert(0); // wrong constructor
 #else
-	otherProcess_ = new IPCProcess(context_, clientRead, clientWrite, INVALID_IPCHANDLE_VALUE);
+    otherProcess_ = new IPCProcess(context_, clientRead, clientWrite, INVALID_IPCHANDLE_VALUE);
 
-	if (!transport_.OpenClient(clientRead, clientWrite))
-	{
+    if (!transport_.OpenClient(clientRead, clientWrite))
+    {
         ATOMIC_LOGERRORF("Unable to open IPC transport clientRead = %i", clientRead);
-		shouldRun_ = false;
-		return;
-	}
+        shouldRun_ = false;
+        return;
+    }
 
     ATOMIC_LOGERRORF("Opened IPC transport fd = %i", clientRead);
 
@@ -59,11 +59,11 @@ IPCWorker::IPCWorker(Context* context, IPCHandle clientRead, IPCHandle clientWri
 
 IPCWorker::IPCWorker(Context* context, IPCHandle fd, unsigned id) : IPCChannel(context, id),
     clientRead_(fd),
-	clientWrite_(fd)
+    clientWrite_(fd)
 {
 
 #ifdef ATOMIC_PLATFORM_WINDOWS
-	assert(0); // wrong constructor
+    assert(0); // wrong constructor
 #else
     otherProcess_ = new IPCProcess(context_, -1, clientRead_, getppid());
 

+ 6 - 6
Source/Atomic/IPC/IPCWorker.h

@@ -35,12 +35,12 @@ class IPCWorker : public IPCChannel
 
 public:
     /// POSIX Constructor
-	IPCWorker(Context* context, IPCHandle fd, unsigned id);
+    IPCWorker(Context* context, IPCHandle fd, unsigned id);
 
-	// Windows Constructor, two named pipes are used
-	IPCWorker(Context* context, IPCHandle clientRead, IPCHandle clientWrite, unsigned id);
+    // Windows Constructor, two named pipes are used
+    IPCWorker(Context* context, IPCHandle clientRead, IPCHandle clientWrite, unsigned id);
 
-	/// Destruct.
+    /// Destruct.
     virtual ~IPCWorker();
 
     void ThreadFunction();
@@ -49,9 +49,9 @@ public:
 
 private:
 
-	// on unix will be the same
+    // on unix will be the same
     IPCHandle clientRead_;
-	IPCHandle clientWrite_;
+    IPCHandle clientWrite_;
 
 };
 

+ 146 - 146
Source/Atomic/Input/Input.cpp

@@ -1212,8 +1212,8 @@ bool Input::RemoveScreenJoystick(SDL_JoystickID id)
         ATOMIC_LOGERRORF("Failed to remove non-existing screen joystick ID #%d", id);
         return false;
     }
-	// ATOMIC BEGIN
-	/*
+    // ATOMIC BEGIN
+    /*
     JoystickState& state = joysticks_[id];
 
 
@@ -1227,8 +1227,8 @@ bool Input::RemoveScreenJoystick(SDL_JoystickID id)
 
     joysticks_.Erase(id);
 */
-	// ATOMIC END    
-	return true;
+    // ATOMIC END    
+    return true;
 }
 
 void Input::SetScreenJoystickVisible(SDL_JoystickID id, bool enable)
@@ -1349,12 +1349,12 @@ SDL_JoystickID Input::OpenJoystick(unsigned index)
     int joystickID = SDL_JoystickInstanceID(joystick);
 
 // ATOMIC BEGIN
-	SharedPtr<JoystickState> nstate(new JoystickState());
+    SharedPtr<JoystickState> nstate(new JoystickState());
     joysticks_[joystickID] = nstate;
-	JoystickState& state = *nstate;
+    JoystickState& state = *nstate;
 // ATOMIC END
     
-	state.joystick_ = joystick;
+    state.joystick_ = joystick;
     state.joystickID_ = joystickID;
     state.name_ = SDL_JoystickName(joystick);
     if (SDL_IsGameController(index))
@@ -1526,36 +1526,36 @@ TouchState* Input::GetTouch(unsigned index) const
 JoystickState* Input::GetJoystickByIndex(unsigned index)
 {
     unsigned compare = 0;
-	// ATOMIC BEGIN
+    // ATOMIC BEGIN
     for (HashMap<SDL_JoystickID, SharedPtr<JoystickState>>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
     {
         if (compare++ == index)
             return (i->second_);
     }
-	// ATOMIC END
+    // ATOMIC END
 
     return 0;
 }
 
 JoystickState* Input::GetJoystickByName(const String& name)
 {
-	// ATOMIC BEGIN
+    // ATOMIC BEGIN
     for (HashMap<SDL_JoystickID, SharedPtr<JoystickState>>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
     {
         if (i->second_->name_ == name)
             return (i->second_);
     }
-	// ATOMIC END
+    // ATOMIC END
 
     return 0;
 }
 
 JoystickState* Input::GetJoystick(SDL_JoystickID id)
 {
-	// ATOMIC BEGIN
+    // ATOMIC BEGIN
     HashMap<SDL_JoystickID, SharedPtr<JoystickState>>::Iterator i = joysticks_.Find(id);
     return i != joysticks_.End() ? (i->second_) : 0;
-	// ATOMIC END
+    // ATOMIC END
 }
 
 bool Input::IsScreenJoystickVisible(SDL_JoystickID id) const
@@ -1661,13 +1661,13 @@ void Input::ResetInputAccumulation()
     mouseButtonPress_ = 0;
     mouseMove_ = IntVector2::ZERO;
     mouseMoveWheel_ = 0;
-	// ATOMIC BEGIN
+    // ATOMIC BEGIN
     for (HashMap<SDL_JoystickID, SharedPtr<JoystickState>>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
     {
         for (unsigned j = 0; j < i->second_->buttonPress_.Size(); ++j)
             i->second_->buttonPress_[j] = false;
     }
-	// ATOMIC END
+    // ATOMIC END
 
     // Reset touch delta movement
     for (HashMap<int, TouchState>::Iterator i = touches_.Begin(); i != touches_.End(); ++i)
@@ -1730,10 +1730,10 @@ void Input::ResetState()
     scancodePress_.Clear();
 
     /// \todo Check if resetting joystick state on input focus loss is even necessary
-	// ATOMIC BEGIN
+    // ATOMIC BEGIN
     for (HashMap<SDL_JoystickID, SharedPtr<JoystickState>>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
         i->second_->Reset();
-	// ATOMIC END
+    // ATOMIC END
 
     ResetTouches();
 
@@ -2305,27 +2305,27 @@ void Input::HandleSDLEvent(void* sdlEvent)
             unsigned button = evt.jbutton.button;
             SDL_JoystickID joystickID = evt.jbutton.which;
 
-			// ATOMIC BEGIN
-			if (joysticks_.Contains(joystickID))
-			{
-				JoystickState* state = joysticks_[joystickID];
-
-				// Skip ordinary joystick event for a controller
-				if (!state->controller_)
-				{
-					VariantMap& eventData = GetEventDataMap();
-					eventData[P_JOYSTICKID] = joystickID;
-					eventData[P_BUTTON] = button;
-
-					if (button < state->buttons_.Size())
-					{
-						state->buttons_[button] = true;
-						state->buttonPress_[button] = true;
-						SendEvent(E_JOYSTICKBUTTONDOWN, eventData);
-					}
-				}
-			}
-			// ATOMIC END
+            // ATOMIC BEGIN
+            if (joysticks_.Contains(joystickID))
+            {
+                JoystickState* state = joysticks_[joystickID];
+
+                // Skip ordinary joystick event for a controller
+                if (!state->controller_)
+                {
+                    VariantMap& eventData = GetEventDataMap();
+                    eventData[P_JOYSTICKID] = joystickID;
+                    eventData[P_BUTTON] = button;
+
+                    if (button < state->buttons_.Size())
+                    {
+                        state->buttons_[button] = true;
+                        state->buttonPress_[button] = true;
+                        SendEvent(E_JOYSTICKBUTTONDOWN, eventData);
+                    }
+                }
+            }
+            // ATOMIC END
         }
         break;
 
@@ -2336,26 +2336,26 @@ void Input::HandleSDLEvent(void* sdlEvent)
             unsigned button = evt.jbutton.button;
             SDL_JoystickID joystickID = evt.jbutton.which;
 
-			// ATOMIC BEGIN
-			if (joysticks_.Contains(joystickID))
-			{
-				JoystickState* state = joysticks_[joystickID];
-
-				if (!state->controller_)
-				{
-					VariantMap& eventData = GetEventDataMap();
-					eventData[P_JOYSTICKID] = joystickID;
-					eventData[P_BUTTON] = button;
-
-					if (button < state->buttons_.Size())
-					{
-						if (!state->controller_)
-							state->buttons_[button] = false;
-						SendEvent(E_JOYSTICKBUTTONUP, eventData);
-					}
-				}
-			}
-			// ATOMIC END
+            // ATOMIC BEGIN
+            if (joysticks_.Contains(joystickID))
+            {
+                JoystickState* state = joysticks_[joystickID];
+
+                if (!state->controller_)
+                {
+                    VariantMap& eventData = GetEventDataMap();
+                    eventData[P_JOYSTICKID] = joystickID;
+                    eventData[P_BUTTON] = button;
+
+                    if (button < state->buttons_.Size())
+                    {
+                        if (!state->controller_)
+                            state->buttons_[button] = false;
+                        SendEvent(E_JOYSTICKBUTTONUP, eventData);
+                    }
+                }
+            }
+            // ATOMIC END
         }
         break;
 
@@ -2365,30 +2365,30 @@ void Input::HandleSDLEvent(void* sdlEvent)
 
             SDL_JoystickID joystickID = evt.jaxis.which;
 
-			// ATOMIC BEGIN
-			if (joysticks_.Contains(joystickID))
-			{
-
-				JoystickState* state = joysticks_[joystickID];
-
-				if (!state->controller_)
-				{
-					VariantMap& eventData = GetEventDataMap();
-					eventData[P_JOYSTICKID] = joystickID;
-					eventData[P_AXIS] = evt.jaxis.axis;
-					eventData[P_POSITION] = Clamp((float)evt.jaxis.value / 32767.0f, -1.0f, 1.0f);
-
-					if (evt.jaxis.axis < state->axes_.Size())
-					{
-						// If the joystick is a controller, only use the controller axis mappings
-						// (we'll also get the controller event)
-						if (!state->controller_)
-							state->axes_[evt.jaxis.axis] = eventData[P_POSITION].GetFloat();
-						SendEvent(E_JOYSTICKAXISMOVE, eventData);
-					}
-				}
-			}
-			// ATOMIC END
+            // ATOMIC BEGIN
+            if (joysticks_.Contains(joystickID))
+            {
+
+                JoystickState* state = joysticks_[joystickID];
+
+                if (!state->controller_)
+                {
+                    VariantMap& eventData = GetEventDataMap();
+                    eventData[P_JOYSTICKID] = joystickID;
+                    eventData[P_AXIS] = evt.jaxis.axis;
+                    eventData[P_POSITION] = Clamp((float)evt.jaxis.value / 32767.0f, -1.0f, 1.0f);
+
+                    if (evt.jaxis.axis < state->axes_.Size())
+                    {
+                        // If the joystick is a controller, only use the controller axis mappings
+                        // (we'll also get the controller event)
+                        if (!state->controller_)
+                            state->axes_[evt.jaxis.axis] = eventData[P_POSITION].GetFloat();
+                        SendEvent(E_JOYSTICKAXISMOVE, eventData);
+                    }
+                }
+            }
+            // ATOMIC END
         }
         break;
 
@@ -2397,23 +2397,23 @@ void Input::HandleSDLEvent(void* sdlEvent)
             using namespace JoystickHatMove;
 
             SDL_JoystickID joystickID = evt.jaxis.which;
-			// ATOMIC BEGIN
-			if (joysticks_.Contains(joystickID))
-			{
-				JoystickState* state = joysticks_[joystickID];
-
-				VariantMap& eventData = GetEventDataMap();
-				eventData[P_JOYSTICKID] = joystickID;
-				eventData[P_HAT] = evt.jhat.hat;
-				eventData[P_POSITION] = evt.jhat.value;
-
-				if (evt.jhat.hat < state->hats_.Size())
-				{
-					state->hats_[evt.jhat.hat] = evt.jhat.value;
-					SendEvent(E_JOYSTICKHATMOVE, eventData);
-				}
-			}
-			// ATOMIC END
+            // ATOMIC BEGIN
+            if (joysticks_.Contains(joystickID))
+            {
+                JoystickState* state = joysticks_[joystickID];
+
+                VariantMap& eventData = GetEventDataMap();
+                eventData[P_JOYSTICKID] = joystickID;
+                eventData[P_HAT] = evt.jhat.hat;
+                eventData[P_POSITION] = evt.jhat.value;
+
+                if (evt.jhat.hat < state->hats_.Size())
+                {
+                    state->hats_[evt.jhat.hat] = evt.jhat.value;
+                    SendEvent(E_JOYSTICKHATMOVE, eventData);
+                }
+            }
+            // ATOMIC END
         }
         break;
 
@@ -2424,24 +2424,24 @@ void Input::HandleSDLEvent(void* sdlEvent)
             unsigned button = evt.cbutton.button;
             SDL_JoystickID joystickID = evt.cbutton.which;
 
-			// ATOMIC BEGIN
-			if (joysticks_.Contains(joystickID))
-			{
+            // ATOMIC BEGIN
+            if (joysticks_.Contains(joystickID))
+            {
 
-				JoystickState* state = joysticks_[joystickID];
+                JoystickState* state = joysticks_[joystickID];
 
-				VariantMap& eventData = GetEventDataMap();
-				eventData[P_JOYSTICKID] = joystickID;
-				eventData[P_BUTTON] = button;
+                VariantMap& eventData = GetEventDataMap();
+                eventData[P_JOYSTICKID] = joystickID;
+                eventData[P_BUTTON] = button;
 
-				if (button < state->buttons_.Size())
-				{
-					state->buttons_[button] = true;
-					state->buttonPress_[button] = true;
-					SendEvent(E_JOYSTICKBUTTONDOWN, eventData);
-				}
-			}
-			// ATOMIC END
+                if (button < state->buttons_.Size())
+                {
+                    state->buttons_[button] = true;
+                    state->buttonPress_[button] = true;
+                    SendEvent(E_JOYSTICKBUTTONDOWN, eventData);
+                }
+            }
+            // ATOMIC END
         }
         break;
 
@@ -2452,22 +2452,22 @@ void Input::HandleSDLEvent(void* sdlEvent)
             unsigned button = evt.cbutton.button;
             SDL_JoystickID joystickID = evt.cbutton.which;
 
-			// ATOMIC BEGIN
-			if (joysticks_.Contains(joystickID))
-			{
-				JoystickState* state = joysticks_[joystickID];
-
-				VariantMap& eventData = GetEventDataMap();
-				eventData[P_JOYSTICKID] = joystickID;
-				eventData[P_BUTTON] = button;
-
-				if (button < state->buttons_.Size())
-				{
-					state->buttons_[button] = false;
-					SendEvent(E_JOYSTICKBUTTONUP, eventData);
-				}
-			}
-			// ATOMIC END
+            // ATOMIC BEGIN
+            if (joysticks_.Contains(joystickID))
+            {
+                JoystickState* state = joysticks_[joystickID];
+
+                VariantMap& eventData = GetEventDataMap();
+                eventData[P_JOYSTICKID] = joystickID;
+                eventData[P_BUTTON] = button;
+
+                if (button < state->buttons_.Size())
+                {
+                    state->buttons_[button] = false;
+                    SendEvent(E_JOYSTICKBUTTONUP, eventData);
+                }
+            }
+            // ATOMIC END
         }
         break;
 
@@ -2477,22 +2477,22 @@ void Input::HandleSDLEvent(void* sdlEvent)
 
             SDL_JoystickID joystickID = evt.caxis.which;
 
-			// ATOMIC BEGIN
-			if (joysticks_.Contains(joystickID))
-			{
-				JoystickState* state = joysticks_[joystickID];
-
-				VariantMap& eventData = GetEventDataMap();
-				eventData[P_JOYSTICKID] = joystickID;
-				eventData[P_AXIS] = evt.caxis.axis;
-				eventData[P_POSITION] = Clamp((float)evt.caxis.value / 32767.0f, -1.0f, 1.0f);
-
-				if (evt.caxis.axis < state->axes_.Size())
-				{
-					state->axes_[evt.caxis.axis] = eventData[P_POSITION].GetFloat();
-					SendEvent(E_JOYSTICKAXISMOVE, eventData);
-				}
-			}
+            // ATOMIC BEGIN
+            if (joysticks_.Contains(joystickID))
+            {
+                JoystickState* state = joysticks_[joystickID];
+
+                VariantMap& eventData = GetEventDataMap();
+                eventData[P_JOYSTICKID] = joystickID;
+                eventData[P_AXIS] = evt.caxis.axis;
+                eventData[P_POSITION] = Clamp((float)evt.caxis.value / 32767.0f, -1.0f, 1.0f);
+
+                if (evt.caxis.axis < state->axes_.Size())
+                {
+                    state->axes_[evt.caxis.axis] = eventData[P_POSITION].GetFloat();
+                    SendEvent(E_JOYSTICKAXISMOVE, eventData);
+                }
+            }
         }
         break;
 

+ 7 - 7
Source/Atomic/Input/Input.h

@@ -79,7 +79,7 @@ struct TouchState
 // ATOMIC BEGIN
 class JoystickState : public RefCounted
 {
-	ATOMIC_REFCOUNTED(JoystickState)
+    ATOMIC_REFCOUNTED(JoystickState)
 // ATOMIC END
 
 public:
@@ -334,12 +334,12 @@ public:
     void JoystickSimulateMouseMove(int xpos, int ypos); /// moves the on screen cursor
     void JoystickSimulateMouseButton(int button); /// simulated mouse press down & up
 
-	int GetTouchID(unsigned index) { if (index >= touches_.Size()) return 0; return touches_[index].touchID_; }
-	const IntVector2& GetTouchPosition(unsigned index) { if (index >= touches_.Size()) return IntVector2::ZERO; return touches_[index].position_; }
-	const IntVector2& GetTouchLastPosition(unsigned index) { if (index >= touches_.Size()) return IntVector2::ZERO; return touches_[index].lastPosition_; }
-	const IntVector2& GetTouchDelta(unsigned index) { if (index >= touches_.Size()) return IntVector2::ZERO; return touches_[index].delta_; }
-	const float GetTouchPressure(unsigned index) { if (index >= touches_.Size()) return 0.0f; return touches_[index].pressure_; }
-	UIWidget* GetTouchWidget(unsigned index) { if (index >= touches_.Size()) return 0; return touches_[index].touchedWidget_; }	
+    int GetTouchID(unsigned index) { if (index >= touches_.Size()) return 0; return touches_[index].touchID_; }
+    const IntVector2& GetTouchPosition(unsigned index) { if (index >= touches_.Size()) return IntVector2::ZERO; return touches_[index].position_; }
+    const IntVector2& GetTouchLastPosition(unsigned index) { if (index >= touches_.Size()) return IntVector2::ZERO; return touches_[index].lastPosition_; }
+    const IntVector2& GetTouchDelta(unsigned index) { if (index >= touches_.Size()) return IntVector2::ZERO; return touches_[index].delta_; }
+    const float GetTouchPressure(unsigned index) { if (index >= touches_.Size()) return 0.0f; return touches_[index].pressure_; }
+    UIWidget* GetTouchWidget(unsigned index) { if (index >= touches_.Size()) return 0; return touches_[index].touchedWidget_; }    
 
 // ATOMIC END
 

+ 4 - 4
Source/Atomic/UI/UIDragDropWindows.cpp

@@ -60,8 +60,8 @@ namespace Atomic
     public:
         // IUnknown implementation
         HRESULT __stdcall QueryInterface(REFIID iid, void ** ppvObject);
-        ULONG	__stdcall AddRef(void);
-        ULONG	__stdcall Release(void);
+        ULONG    __stdcall AddRef(void);
+        ULONG    __stdcall Release(void);
 
         void UpdateMousePos();
 
@@ -84,8 +84,8 @@ namespace Atomic
         bool  QueryDataObject(IDataObject *pDataObject);
 
         // Private member variables
-        LONG	m_lRefCount;
-        HWND	m_hWnd;
+        LONG    m_lRefCount;
+        HWND    m_hWnd;
         bool    m_fAllowDrop;
 
         IDataObject *m_pDataObject;

+ 4 - 4
Source/Atomic/UI/UIInput.cpp

@@ -37,10 +37,10 @@ namespace Atomic
 static MODIFIER_KEYS GetModifierKeys(int qualifiers, bool superKey)
 {
     MODIFIER_KEYS code = TB_MODIFIER_NONE;
-    if (qualifiers & QUAL_ALT)	code |= TB_ALT;
-    if (qualifiers & QUAL_CTRL)	code |= TB_CTRL;
-    if (qualifiers & QUAL_SHIFT)	code |= TB_SHIFT;
-    if (superKey)	code |= TB_SUPER;
+    if (qualifiers & QUAL_ALT)    code |= TB_ALT;
+    if (qualifiers & QUAL_CTRL)    code |= TB_CTRL;
+    if (qualifiers & QUAL_SHIFT)    code |= TB_SHIFT;
+    if (superKey)    code |= TB_SUPER;
     return code;
 }
 

+ 3 - 3
Source/Atomic/UI/UILayout.h

@@ -30,8 +30,8 @@ namespace Atomic
 {
 
 /// Specifies which height widgets in a AXIS_X layout should have,
-///	or which width widgets in a AXIS_Y layout should have.
-///	No matter what, it will still prioritize minimum and maximum for each widget.
+///    or which width widgets in a AXIS_Y layout should have.
+///    No matter what, it will still prioritize minimum and maximum for each widget.
 enum UI_LAYOUT_SIZE
 {
     /// Sizes depend on the gravity for each widget. (If the widget pulls
@@ -60,7 +60,7 @@ enum UI_LAYOUT_DISTRIBUTION
 };
 
 /// Specifies which y position widgets in a AXIS_X layout should have,
-///	or which x position widgets in a AXIS_Y layout should have. */
+///    or which x position widgets in a AXIS_Y layout should have. */
 enum UI_LAYOUT_POSITION
 {
     ///< Position is centered

+ 4 - 4
Source/Atomic/UI/UIPreferredSize.h

@@ -36,13 +36,13 @@ namespace Atomic
 /// Defines how the size in one axis depend on the other axis when a widgets size is affected by constraints.
 enum UI_SIZE_DEP {
     /// No dependency (Faster layout).
-    UI_SIZE_DEP_NONE						= tb::SIZE_DEP_NONE,
+    UI_SIZE_DEP_NONE                        = tb::SIZE_DEP_NONE,
     /// The width is dependant on the height. Additional layout pass may be required.
-    UI_SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT		= tb::SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT,
+    UI_SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT        = tb::SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT,
     /// The height is dependant on the width. Additional layout pass may be required.
-    UI_SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH		= tb::SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH,
+    UI_SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH        = tb::SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH,
     /// Both width and height are dependant on each other. Additional layout pass may be required.
-    UI_SIZE_DEP_BOTH						=	tb::SIZE_DEP_BOTH
+    UI_SIZE_DEP_BOTH                        =    tb::SIZE_DEP_BOTH
 };
 
 class UIPreferredSize : public RefCounted

+ 5 - 5
Source/Atomic/UI/UIScrollContainer.h

@@ -30,15 +30,15 @@ namespace Atomic
 {
 
 enum UI_SCROLL_MODE {
-    ///< X and Y always			scroll-mode: xy
+    ///< X and Y always            scroll-mode: xy
     UI_SCROLL_MODE_X_Y = tb::SCROLL_MODE_X_Y,
-    ///< Y always (X never)		scroll-mode: y
+    ///< Y always (X never)        scroll-mode: y
     UI_SCROLL_MODE_Y = tb::SCROLL_MODE_Y,
-    ///< Y auto (X never)		scroll-mode: y-auto
+    ///< Y auto (X never)        scroll-mode: y-auto
     UI_SCROLL_MODE_Y_AUTO = tb::SCROLL_MODE_Y_AUTO,
-    ///< X auto, Y auto			scroll-mode: auto
+    ///< X auto, Y auto            scroll-mode: auto
     UI_SCROLL_MODE_X_AUTO_Y_AUTO = tb::SCROLL_MODE_X_AUTO_Y_AUTO,
-    ///< X any Y never			scroll-mode: off
+    ///< X any Y never            scroll-mode: off
     UI_SCROLL_MODE_OFF = tb::SCROLL_MODE_OFF
 };
 

+ 6 - 6
Source/Atomic/UI/UIWidget.h

@@ -55,10 +55,10 @@ enum UI_GRAVITY {
     UI_GRAVITY_TOP = tb::WIDGET_GRAVITY_TOP,
     UI_GRAVITY_BOTTOM = tb::WIDGET_GRAVITY_BOTTOM,
 
-    UI_GRAVITY_LEFT_RIGHT	= tb::WIDGET_GRAVITY_LEFT_RIGHT,
-    UI_GRAVITY_TOP_BOTTOM	= tb::WIDGET_GRAVITY_TOP_BOTTOM,
-    UI_GRAVITY_ALL			= tb::WIDGET_GRAVITY_ALL,
-    UI_GRAVITY_DEFAULT		= tb::WIDGET_GRAVITY_DEFAULT
+    UI_GRAVITY_LEFT_RIGHT    = tb::WIDGET_GRAVITY_LEFT_RIGHT,
+    UI_GRAVITY_TOP_BOTTOM    = tb::WIDGET_GRAVITY_TOP_BOTTOM,
+    UI_GRAVITY_ALL            = tb::WIDGET_GRAVITY_ALL,
+    UI_GRAVITY_DEFAULT        = tb::WIDGET_GRAVITY_DEFAULT
 };
 
 enum UI_EVENT_TYPE {
@@ -119,8 +119,8 @@ enum UI_EVENT_TYPE {
 
 /** Defines widget z level relative to another widget, used with TBWidget::AddChildRelative. */
 enum UI_WIDGET_Z_REL {
-    UI_WIDGET_Z_REL_BEFORE = tb::WIDGET_Z_REL_BEFORE,		///< Before the reference widget (visually behind reference).
-    UI_WIDGET_Z_REL_AFTER = tb::WIDGET_Z_REL_AFTER			///< After the reference widget (visually above reference).
+    UI_WIDGET_Z_REL_BEFORE = tb::WIDGET_Z_REL_BEFORE,        ///< Before the reference widget (visually behind reference).
+    UI_WIDGET_Z_REL_AFTER = tb::WIDGET_Z_REL_AFTER            ///< After the reference widget (visually above reference).
 };
 
 /// TB_TEXT_ALIGN specifies horizontal text alignment

+ 5 - 5
Source/Atomic/UI/UIWindow.h

@@ -32,15 +32,15 @@ namespace Atomic
 
 enum UI_WINDOW_SETTINGS {
     ///< Chrome less window without any other settings.
-    UI_WINDOW_SETTINGS_NONE			= tb::WINDOW_SETTINGS_NONE,
+    UI_WINDOW_SETTINGS_NONE            = tb::WINDOW_SETTINGS_NONE,
     ///< Show a title bar that can also move the window.
-    UI_WINDOW_SETTINGS_TITLEBAR		= tb::WINDOW_SETTINGS_TITLEBAR,
+    UI_WINDOW_SETTINGS_TITLEBAR        = tb::WINDOW_SETTINGS_TITLEBAR,
     ///< Show a widget for resizing the window.
-    UI_WINDOW_SETTINGS_RESIZABLE	= tb::WINDOW_SETTINGS_RESIZABLE,
+    UI_WINDOW_SETTINGS_RESIZABLE    = tb::WINDOW_SETTINGS_RESIZABLE,
     ///< Show a widget for closing the window.
-    UI_WINDOW_SETTINGS_CLOSE_BUTTON	= tb::WINDOW_SETTINGS_CLOSE_BUTTON,
+    UI_WINDOW_SETTINGS_CLOSE_BUTTON    = tb::WINDOW_SETTINGS_CLOSE_BUTTON,
     ///< Can be activated and deactivate other windows.
-    UI_WINDOW_SETTINGS_CAN_ACTIVATE	= tb::WINDOW_SETTINGS_CAN_ACTIVATE,
+    UI_WINDOW_SETTINGS_CAN_ACTIVATE    = tb::WINDOW_SETTINGS_CAN_ACTIVATE,
 
     UI_WINDOW_SETTINGS_DEFAULT = tb::WINDOW_SETTINGS_DEFAULT
 };

+ 9 - 9
Source/AtomicApp/AppBase.cpp

@@ -114,18 +114,18 @@ namespace Atomic
 
     }
 
-	bool AppBase::RunFrame()
-	{
-		engine_->RunFrame();
+    bool AppBase::RunFrame()
+    {
+        engine_->RunFrame();
 
-		if (engine_->IsExiting())
-		{
-			return false;
-		}
+        if (engine_->IsExiting())
+        {
+            return false;
+        }
 
-		return true;
+        return true;
 
-	}
+    }
 
     void AppBase::Stop()
     {

+ 3 - 3
Source/AtomicApp/AppBase.h

@@ -45,10 +45,10 @@ namespace Atomic
         /// Cleanup after the main loop. 
         virtual void Stop();
 
-		/// Run a single frame, return's true if engine is exiting
-		bool RunFrame();
+        /// Run a single frame, return's true if engine is exiting
+        bool RunFrame();
 
-		virtual void Shutdown() { Stop(); }
+        virtual void Shutdown() { Stop(); }
 
         static void AddArgument(const String& argument) { arguments_.Push(argument); }
 

+ 12 - 12
Source/AtomicEditor/EditorMode/AEEditorMode.cpp

@@ -141,10 +141,10 @@ bool EditorMode::PlayProject(String addArgs, bool debug)
 
     String playerBinary = env->GetEditorBinary();
 
-	ProjectSettings* settings = project->GetProjectSettings();
+    ProjectSettings* settings = project->GetProjectSettings();
 
-	String projectAssembly = settings->GetName() + ".dll";
-	String projectExe = settings->GetName() + ".exe";
+    String projectAssembly = settings->GetName() + ".dll";
+    String projectExe = settings->GetName() + ".exe";
 
     // TODO: We need to configure project as managed
     bool managed = false;
@@ -154,22 +154,22 @@ bool EditorMode::PlayProject(String addArgs, bool debug)
 
 #ifdef ATOMIC_DEV_BUILD
 
-#ifdef ATOMIC_DEBUG		
-		playerBinary = project->GetProjectPath() + "AtomicNET/Debug/Bin/Desktop/" + projectExe;
+#ifdef ATOMIC_DEBUG        
+        playerBinary = project->GetProjectPath() + "AtomicNET/Debug/Bin/Desktop/" + projectExe;
 #else
-		playerBinary = project->GetProjectPath() + "AtomicNET/Release/Bin/Desktop/" + projectExe;
+        playerBinary = project->GetProjectPath() + "AtomicNET/Release/Bin/Desktop/" + projectExe;
 #endif
 
 #else
-		// TODO: We are using the release build of the managed project here, how and when to use debug?
-		playerBinary = project->GetProjectPath() + "AtomicNET/Release/Bin/Desktop/" + projectExe;
+        // TODO: We are using the release build of the managed project here, how and when to use debug?
+        playerBinary = project->GetProjectPath() + "AtomicNET/Release/Bin/Desktop/" + projectExe;
 #endif
 
         
-		if (!fileSystem->FileExists(playerBinary))
-		{
-			ATOMIC_LOGERRORF("Managed player: %s does not exist", playerBinary.CString());
-		}
+        if (!fileSystem->FileExists(playerBinary))
+        {
+            ATOMIC_LOGERRORF("Managed player: %s does not exist", playerBinary.CString());
+        }
 
     }
 

+ 1 - 1
Source/AtomicJS/Javascript/JSComponent.h

@@ -78,7 +78,7 @@ public:
 
     void SetDestroyed() { destroyed_ = true; }
 
-    bool IsInstanceInitialized();	
+    bool IsInstanceInitialized();    
     void InitInstance(bool hasArgs = false, int argIdx = 0);
 
     /// Get script attribute

+ 5 - 5
Source/AtomicJS/Javascript/JSEvents.h

@@ -28,11 +28,11 @@ namespace Atomic
 {
 
 /*
-name	standard	Name of error, e.g. TypeError, inherited
-message	standard	Optional message of error, own property, empty message inherited if absent
-fileName	Rhino	Filename related to error source, inherited accessor
-lineNumber	Rhino	Linenumber related to error source, inherited accessor
-stack	V8	Traceback as a multi-line human redable string, inherited accessor
+name    standard    Name of error, e.g. TypeError, inherited
+message    standard    Optional message of error, own property, empty message inherited if absent
+fileName    Rhino    Filename related to error source, inherited accessor
+lineNumber    Rhino    Linenumber related to error source, inherited accessor
+stack    V8    Traceback as a multi-line human redable string, inherited accessor
 */
 
 ATOMIC_EVENT(E_JSOBJECTADDED, ObjectAdded)

+ 27 - 0
Source/AtomicNET/NETNative/CMakeLists.txt

@@ -5,6 +5,12 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
                     ${CMAKE_SOURCE_DIR}/Source/ThirdParty/FreeType/include
                     ${CMAKE_SOURCE_DIR}/Source/ThirdParty/Box2D)
 
+# TODO: Look into the application-extension flag for iOS
+#if (IOS)
+#    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fapplication-extension")
+#    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fapplication-extension")
+#endif()
+
 set (CSATOMICDIR "${CMAKE_SOURCE_DIR}/Artifacts/Build/Source/Generated/CSharp/Packages/")
 
 file (GLOB CSHARP_BINDINGS_SOURCE ${CSATOMICDIR}/Atomic/Native/*.cpp ${CSATOMICDIR}/Atomic/Native/*.h
@@ -44,6 +50,18 @@ if (APPLE)
 
         target_link_libraries( AtomicNETNative "-stdlib=libc++ -framework AudioUnit -framework Carbon -framework Cocoa -framework CoreAudio -framework CoreVideo -framework ForceFeedback -framework IOKit -framework OpenGL -framework CoreServices -framework Security")
 
+    else()
+
+        set_target_properties(AtomicNETNative PROPERTIES
+          FRAMEWORK TRUE
+          MACOSX_FRAMEWORK_IDENTIFIER com.atomicgameengine.atomicnetframework
+          MACOSX_FRAMEWORK_INFO_PLIST ${CMAKE_SOURCE_DIR}/Build/CMake/IOS/AtomicNET.framework.plist
+          # PUBLIC_HEADER dynamicFramework.h
+          XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer"
+        )
+
+        target_link_libraries( AtomicNETNative "-framework AudioToolbox -framework CoreAudio -framework CoreGraphics -framework Foundation -framework OpenGLES -framework QuartzCore -framework UIKit -framework CoreMotion -framework GameController")
+
     endif()
 
 endif()
@@ -64,10 +82,19 @@ endif()
 
 set (ATOMICNET_NATIVE_DIR "${CMAKE_SOURCE_DIR}/Artifacts/AtomicNET/$<$<CONFIG:debug>:Debug>$<$<CONFIG:release>:Release>/Native/${ATOMICNET_NATIVE_PLATFORM}")
 
+if (NOT IOS)
+
 add_custom_command( TARGET AtomicNETNative POST_BUILD
                     COMMAND "${CMAKE_COMMAND}" ARGS -E make_directory "\"${ATOMICNET_NATIVE_DIR}\""
                     COMMAND "${CMAKE_COMMAND}" ARGS -E copy_if_different \"$<TARGET_FILE:AtomicNETNative>\" "\"${ATOMICNET_NATIVE_DIR}\"" )
 
+else()
+
+    # See BuildIOS.js for handling of the AtomicNETNative framework, including install_name_tool modification, etc
+    # Handling it here was causing issues with certain builds of XCode and where it thought the TARGET_FILE was...
+
+endif()
+
 if (MSVC)
 
     # Copy the D3D shader compiler (for pre-Windows 8)

+ 8 - 8
Source/AtomicNET/NETNative/Desktop/NETIPCPlayerApp.cpp

@@ -50,14 +50,14 @@ namespace Atomic
     {
         IPCPlayerApp::Setup();
 
-		// TODO: we should always have a --project for IPCPlayer, however it is doing 
-		// double duty right now as managed player
-		StringVector args = GetArguments();
-		if (!args.Contains("--project"))
-		{
-			engineParameters_["ResourcePrefixPaths"] = "AtomicPlayer_Resources";
-			engineParameters_["ResourcePaths"] = "AtomicResources";
-		}
+        // TODO: we should always have a --project for IPCPlayer, however it is doing 
+        // double duty right now as managed player
+        StringVector args = GetArguments();
+        if (!args.Contains("--project"))
+        {
+            engineParameters_["ResourcePrefixPaths"] = "AtomicPlayer_Resources";
+            engineParameters_["ResourcePaths"] = "AtomicResources";
+        }
     }
 
     int NETIPCPlayerApp::Initialize()

+ 14 - 12
Source/AtomicNET/NETNative/NETAtomicPlayer.cpp

@@ -38,7 +38,7 @@
 #include <stdio.h>
 #endif
 
-// Android or iOS: use SDL_main
+// Android: uses SDL_main, defined for IOS only to satifsy linker
 #if defined(__ANDROID__) || defined(IOS)
 
 typedef int(*sdl_entry_callback)();
@@ -47,18 +47,20 @@ static sdl_entry_callback sdlEntryCallback = 0;
 
 extern "C" void RegisterSDLEntryCallback(sdl_entry_callback callback)
 {
-	sdlEntryCallback = callback;
+    sdlEntryCallback = callback;
 }
 
-extern "C" int SDL_main(int argc, char** argv); 
-int SDL_main(int argc, char** argv) 
-{ 
-    Atomic::ParseArguments(argc, argv); 
-	if (sdlEntryCallback != 0)
-	{
-		return sdlEntryCallback();
-	}
-	return 0;
+extern "C" int SDL_main(int argc, char** argv);
+int SDL_main(int argc, char** argv)
+{
+#if defined(__ANDROID__)
+    Atomic::ParseArguments(argc, argv);
+    if (sdlEntryCallback != 0)
+    {
+        return sdlEntryCallback();
+    }
+#endif    
+    return 0;
 }
 #endif
 
@@ -75,7 +77,7 @@ namespace Atomic
     {
         PlayerApp::Setup();
 
-		engineParameters_["ResourcePaths"] = "AtomicResources"; 
+        engineParameters_["ResourcePaths"] = "AtomicResources";
     }
 
     int NETAtomicPlayer::Initialize()

+ 53 - 2
Source/AtomicNET/NETNative/NETCInterop.cpp

@@ -22,6 +22,11 @@
 namespace Atomic
 {
 
+#ifdef ATOMIC_PLATFORM_IOS
+    static const char *sdlResourceDir = 0;
+    static const char *sdlDocumentsDir = 0;
+#endif
+
     extern "C"
     {
 
@@ -60,10 +65,16 @@ namespace Atomic
             obj->SendEvent(eventType, vmap ? vmap->GetVariantMap() : obj->GetEventDataMap());
         }
 
-        ATOMIC_EXPORT_API ClassID csi_Atomic_NETCore_Initialize(NETCoreDelegates* delegates)
+        ATOMIC_EXPORT_API ClassID csi_Atomic_NETCore_Initialize(NETCoreEventDispatchFunction eventDispatch, NETCoreUpdateDispatchFunction updateDispatch)
         {
             Context* context = new Context();
-            NETCore* netCore = new NETCore(context, delegates);
+
+            // NOTE: We don't simply marshal the NETCoreDelegates structure due to iOS "reverse callback" limitation
+            NETCoreDelegates delegates;
+            delegates.eventDispatch = eventDispatch;
+            delegates.updateDispatch = updateDispatch;
+
+            NETCore* netCore = new NETCore(context, &delegates);
             context->RegisterSubsystem(netCore);
             return netCore;
         }
@@ -123,6 +134,20 @@ namespace Atomic
 
         }
 
+        // Graphics
+
+        ATOMIC_EXPORT_API void* csi_Atomic_Graphics_GetSDLWindow()
+        {
+            if (!NETCore::GetContext())
+                return 0;
+
+            if (!NETCore::GetContext()->GetSubsystem<Graphics>())
+                return 0;
+
+            return NETCore::GetContext()->GetSubsystem<Graphics>()->GetSDLWindow();
+
+        }
+
         ATOMIC_EXPORT_API void* csi_Atomic_VertexBuffer_Lock(VertexBuffer* vb , unsigned start, unsigned count, bool discard)
         {
             if (!vb)
@@ -140,9 +165,35 @@ namespace Atomic
             graphics->SetShaderParameter(param, *matrix);
         }
 
+#ifdef ATOMIC_PLATFORM_IOS
+        ATOMIC_EXPORT_API void SDL_IOS_Init(const char *resourceDir, const char *documentsDir)
+        {
+            sdlResourceDir = resourceDir;
+            sdlDocumentsDir = documentsDir;
+        }
+#endif
+
 
     }
 }
 
+#ifdef ATOMIC_PLATFORM_IOS
+
+//FileSystem.cpp uses these functions as external.
+const char* SDL_IOS_GetResourceDir()
+{
+    return Atomic::sdlResourceDir;
+}
+
+const char* SDL_IOS_GetDocumentsDir()
+{
+    return Atomic::sdlDocumentsDir;
+}
+
+#endif
+
+
+
+
 
 

+ 1 - 1
Source/AtomicNET/NETScript/CSComponentAssembly.cpp

@@ -231,7 +231,7 @@ namespace Atomic
 
     bool CSComponentAssembly::BeginLoad(Deserializer& source)
     {
-		fullAssemblyPath_ = source.GetName();
+        fullAssemblyPath_ = source.GetName();
 
         VariantMap eventData;
 

+ 1 - 1
Source/AtomicPlayer/Application/CMakeLists.txt

@@ -55,7 +55,7 @@ if (APPLE)
       XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer"
       XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym"
       XCODE_ATTRIBUTE_INFOPLIST_PREPROCESS YES
-      XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET 9.2
+      XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET 9.3
       XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2" # iPhone/iPad
       XCODE_ATTRIBUTE_COMBINE_HIDPI_IMAGES NO
     )

+ 5 - 5
Source/AtomicTool/AtomicTool.cpp

@@ -269,11 +269,11 @@ void AtomicTool::Start()
     {
         FileSystem* fileSystem = GetSubsystem<FileSystem>();
 
-		String projectDirectory = cmd->GetProjectPath();
-			
-		// default to current directly if command doesn't provide the path
-		if (!projectDirectory.Length())
-			projectDirectory = fileSystem->GetCurrentDir();
+        String projectDirectory = cmd->GetProjectPath();
+            
+        // default to current directly if command doesn't provide the path
+        if (!projectDirectory.Length())
+            projectDirectory = fileSystem->GetCurrentDir();
 
         Vector<String> projectFiles;
         fileSystem->ScanDir(projectFiles, projectDirectory, "*.atomic", SCAN_FILES, false);

+ 1 - 1
Source/AtomicTool/CMakeLists.txt

@@ -51,5 +51,5 @@ add_custom_target ( GenerateScriptBindings
 
 add_custom_target ( GenerateAtomicNET
                     WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
-                    COMMAND ${ATOMIC_NODE_JAKE};build:genAtomicNET[${JAVASCRIPT_BINDINGS_PLATFORM},$<$<CONFIG:debug>:"Debug">$<$<CONFIG:release>:"Release">];--trace
+                    COMMAND ${ATOMIC_NODE_JAKE};build:genAtomicNET[desktop,$<$<CONFIG:debug>:"Debug">$<$<CONFIG:release>:"Release">];--trace
                     DEPENDS AtomicTool )

+ 1 - 1
Source/CMakeLists.txt

@@ -12,7 +12,7 @@ endif()
 add_subdirectory(AtomicPlayer)
 add_subdirectory(AtomicPlayerJS)
 
-if (NOT IOS AND NOT EMSCRIPTEN)
+if (NOT EMSCRIPTEN)
     add_subdirectory(AtomicApp)
     add_subdirectory(AtomicNET)
 endif()

+ 30 - 30
Source/ToolCore/Assets/TextureImporter.cpp

@@ -36,8 +36,8 @@
 namespace ToolCore
 {
 
-	TextureImporter::TextureImporter(Context* context, Asset *asset) : AssetImporter(context, asset),
-		compressTextures_(false), compressedSize_(0)
+    TextureImporter::TextureImporter(Context* context, Asset *asset) : AssetImporter(context, asset),
+        compressTextures_(false), compressedSize_(0)
 {
     ApplyProjectImportConfig();
 }
@@ -51,7 +51,7 @@ void TextureImporter::SetDefaults()
 {
     AssetImporter::SetDefaults();
 
-	compressedSize_ = 0;
+    compressedSize_ = 0;
 
 }
 
@@ -76,29 +76,29 @@ bool TextureImporter::Import()
     {
         fileSystem->CreateDirs(cachePath, "DDS/" + Atomic::GetPath(asset_->GetRelativePath()));
 
-		float resizefactor;
-		float width = image->GetWidth();
-		float height = image->GetHeight();
-
-		if (width > compressedSize_ || height > compressedSize_)
-		{
-			if (width >= height)
-			{
-				resizefactor = compressedSize_ / width;
-			}
-			else
-			{
-				resizefactor = compressedSize_ / height;
-			}
-
-			image->Resize(width*resizefactor, height*resizefactor);
-		}
-
-		if (image->SaveDDS(compressedPath))
-		{			
-			Renderer * renderer = GetSubsystem<Renderer>();
-			renderer->ReloadTextures();
-		}
+        float resizefactor;
+        float width = image->GetWidth();
+        float height = image->GetHeight();
+
+        if (width > compressedSize_ || height > compressedSize_)
+        {
+            if (width >= height)
+            {
+                resizefactor = compressedSize_ / width;
+            }
+            else
+            {
+                resizefactor = compressedSize_ / height;
+            }
+
+            image->Resize(width*resizefactor, height*resizefactor);
+        }
+
+        if (image->SaveDDS(compressedPath))
+        {            
+            Renderer * renderer = GetSubsystem<Renderer>();
+            renderer->ReloadTextures();
+        }
     }
 
     // todo, proper proportions
@@ -137,10 +137,10 @@ bool TextureImporter::LoadSettingsInternal(JSONValue& jsonRoot)
 
     JSONValue import = jsonRoot.Get("TextureImporter");
 
-	SetDefaults();
+    SetDefaults();
 
-	if (import.Get("compressionSize").IsNumber())
-		compressedSize_ = (CompressedFormat)import.Get("compressionSize").GetInt();
+    if (import.Get("compressionSize").IsNumber())
+        compressedSize_ = (CompressedFormat)import.Get("compressionSize").GetInt();
 
     return true;
 }
@@ -151,7 +151,7 @@ bool TextureImporter::SaveSettingsInternal(JSONValue& jsonRoot)
         return false;
 
     JSONValue import(JSONValue::emptyObject);
-	import.Set("compressionSize", compressedSize_);
+    import.Set("compressionSize", compressedSize_);
 
     jsonRoot.Set("TextureImporter", import);
 

+ 3 - 3
Source/ToolCore/Assets/TextureImporter.h

@@ -41,8 +41,8 @@ public:
     Resource* GetResource(const String& typeName = String::EMPTY);
     Node* InstantiateNode(Node* parent, const String& name);
 
-	void SetCompressedImageSize(unsigned int compressedSize) { compressedSize_ = compressedSize; }
-	unsigned int GetCompressedImageSize() { return compressedSize_; }
+    void SetCompressedImageSize(unsigned int compressedSize) { compressedSize_ = compressedSize; }
+    unsigned int GetCompressedImageSize() { return compressedSize_; }
 
 protected:
 
@@ -54,7 +54,7 @@ protected:
 
     bool compressTextures_;
 
-	unsigned int compressedSize_;
+    unsigned int compressedSize_;
 };
 
 }

+ 10 - 10
Source/ToolCore/Build/BuildBase.cpp

@@ -47,8 +47,8 @@ BuildBase::BuildBase(Context * context, Project* project, PlatformID platform) :
     buildFailed_(false),
     assetBuildTag_(String::EMPTY),
     fileIncludedResourcesLog_(nullptr),
-	resourcesOnly_(false),
-	verbose_(false)
+    resourcesOnly_(false),
+    verbose_(false)
 {
     if (UseResourcePackager())
         resourcePackager_ = new ResourcePackager(context, this);
@@ -336,10 +336,10 @@ void BuildBase::BuildDefaultResourceEntries()
             const String& filename = fileNames[i];
             AddToResourcePackager(filename, resourceDir);
 
-			if (verbose_)
-			{
-				ATOMIC_LOGINFO(ToString("Default Resource Added: %s%s", resourceDir.CString(), filename.CString()));
-			}
+            if (verbose_)
+            {
+                ATOMIC_LOGINFO(ToString("Default Resource Added: %s%s", resourceDir.CString(), filename.CString()));
+            }
         }
     }
 }
@@ -383,10 +383,10 @@ void BuildBase::BuildAllProjectResourceEntries()
         {
             AddToResourcePackager(fileNamesInProject[i], projectResourceDir);
 
-			if (verbose_)
-			{
-				ATOMIC_LOGINFO(ToString("Project Resource Added: %s%s", projectResourceDir.CString(), fileNamesInProject[i].CString()));
-			}
+            if (verbose_)
+            {
+                ATOMIC_LOGINFO(ToString("Project Resource Added: %s%s", projectResourceDir.CString(), fileNamesInProject[i].CString()));
+            }
 
         }
     }

+ 7 - 7
Source/ToolCore/Build/BuildBase.h

@@ -76,13 +76,13 @@ public:
     /// in the build. If no tag is specified, then all resources are included.
     void SetAssetBuildTag(const String assetBuildTag) { assetBuildTag_ = assetBuildTag; }
 
-	void SetVerbose(bool verbose = true) { verbose_ = verbose; }
+    void SetVerbose(bool verbose = true) { verbose_ = verbose; }
 
-	bool GetResourcesOnly() const { return resourcesOnly_; }
-	void SetResourcesOnly(bool resourcesOnly = true) { resourcesOnly_ = resourcesOnly;  }
+    bool GetResourcesOnly() const { return resourcesOnly_; }
+    void SetResourcesOnly(bool resourcesOnly = true) { resourcesOnly_ = resourcesOnly;  }
 
-	bool GetBuildFailed() const { return buildFailed_; }
-	const Vector<String>& GetBuildErrors() const { return buildErrors_; }
+    bool GetBuildFailed() const { return buildFailed_; }
+    const Vector<String>& GetBuildErrors() const { return buildErrors_; }
 
 protected:
 
@@ -116,8 +116,8 @@ protected:
     /// Pointer to a file used to capture the resources included in the build
     File *fileIncludedResourcesLog_;
 
-	bool resourcesOnly_;
-	bool verbose_;
+    bool resourcesOnly_;
+    bool verbose_;
 
 private:
     void BuildFilteredProjectResourceEntries();

+ 22 - 22
Source/ToolCore/Build/BuildWindows.cpp

@@ -98,17 +98,17 @@ bool BuildWindows::BuildManaged(const String& buildPath)
     ToolSystem* toolSystem = GetSubsystem<ToolSystem>();
     FileSystem* fileSystem = GetSubsystem<FileSystem>();
     Project* project = toolSystem->GetProject();
-	ProjectSettings* settings = project->GetProjectSettings();
+    ProjectSettings* settings = project->GetProjectSettings();
 
-	String projectPath = project->GetProjectPath();
-	String releaseBins = projectPath + "AtomicNET/Release/Bin/Desktop/";
-	String releaseExe = releaseBins + settings->GetName() + ".exe";
+    String projectPath = project->GetProjectPath();
+    String releaseBins = projectPath + "AtomicNET/Release/Bin/Desktop/";
+    String releaseExe = releaseBins + settings->GetName() + ".exe";
 
-	if (!fileSystem->FileExists(releaseExe))
-	{
-		BuildError(ToString("Error building managed project, please compile the release binary %s before building", releaseExe.CString()));
-		return false;
-	}
+    if (!fileSystem->FileExists(releaseExe))
+    {
+        BuildError(ToString("Error building managed project, please compile the release binary %s before building", releaseExe.CString()));
+        return false;
+    }
     
     StringVector results;
     StringVector filtered;
@@ -142,7 +142,7 @@ bool BuildWindows::BuildManaged(const String& buildPath)
 
     }
 
-	return true;
+    return true;
   
 }
 
@@ -173,11 +173,11 @@ void BuildWindows::Build(const String& buildPath)
     ToolSystem* tsystem = GetSubsystem<ToolSystem>();
     Project* project = tsystem->GetProject();
 
-	buildPath_ = AddTrailingSlash(buildPath);
+    buildPath_ = AddTrailingSlash(buildPath);
 
-	if (!resourcesOnly_)
-		buildPath_ += GetBuildSubfolder();
-		
+    if (!resourcesOnly_)
+        buildPath_ += GetBuildSubfolder();
+        
     BuildLog("Starting Windows Deployment");
 
     Initialize();
@@ -195,18 +195,18 @@ void BuildWindows::Build(const String& buildPath)
 
     String resourcePackagePath = buildPath_ + "/AtomicPlayer_Resources/AtomicResources" + PAK_EXTENSION;
 
-	if (resourcesOnly_)
-	{
-		resourcePackagePath = buildPath_ + "/AtomicResources" + PAK_EXTENSION;
-	}
+    if (resourcesOnly_)
+    {
+        resourcePackagePath = buildPath_ + "/AtomicResources" + PAK_EXTENSION;
+    }
 
     GenerateResourcePackage(resourcePackagePath);
 
     if (buildFailed_)
         return;
 
-	if (resourcesOnly_)
-		return;
+    if (resourcesOnly_)
+        return;
 
     if (!BuildCreateDirectory(buildPath_ + "/Settings"))
         return;
@@ -223,8 +223,8 @@ void BuildWindows::Build(const String& buildPath)
 
     if (fileSystem->FileExists(project->GetResourcePath() + project->GetProjectSettings()->GetName() + ".dll"))
     {
-		if (!BuildManaged(buildPath))
-			return;
+        if (!BuildManaged(buildPath))
+            return;
     }
     else
     {

+ 1 - 1
Source/ToolCore/Command/Command.h

@@ -63,7 +63,7 @@ public:
 
     virtual bool RequiresProjectLoad() { return true; }
 
-	virtual const String& GetProjectPath() const { return String::EMPTY; }
+    virtual const String& GetProjectPath() const { return String::EMPTY; }
 
     virtual bool RequiresLicenseValidation() { return false; }
 

+ 105 - 71
Source/ToolCore/Command/NETCmd.cpp

@@ -46,7 +46,7 @@ namespace ToolCore
 {
 
 NETCmd::NETCmd(Context* context) : Command(context),
-	requiresProjectLoad_(false)
+    requiresProjectLoad_(false)
 {
 
 }
@@ -67,11 +67,34 @@ bool NETCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String&
         return false;
     }
 
+    if (command_ == "compile" || command_ == "genresources")
+    {
+        for (unsigned i = startIndex + 3; i < arguments.Size(); i++)
+        {
+            if (arguments[i].Length() > 1 && arguments[i][0] == '-')
+            {
+                String argument = arguments[i].Substring(1).ToLower();
+                String value = i + 1 < arguments.Size() ? arguments[i + 1] : String::EMPTY;
+
+                if (argument == "platform" && !value.Empty())
+                {
+                    platforms_.Push(value);
+                    i++;
+                }
+                else if (argument == "config" && !value.Empty())
+                {
+                    configurations_.Push(value);
+                    i++;
+                }
+            }
+        }
+    }
+
     if (command_ == "compile")
     {
+        // solution
         solutionPath_ = startIndex + 2 < arguments.Size() ? arguments[startIndex + 2] : String::EMPTY;
-        platform_ = startIndex + 3 < arguments.Size() ? arguments[startIndex + 3] : String::EMPTY;
-        configuration_ = startIndex + 4 < arguments.Size() ? arguments[startIndex + 4] : "Release";
+
 
         bool exists = false;
 
@@ -87,20 +110,33 @@ bool NETCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String&
             return false;
         }
 
-        if (!platform_.Length())
+        if (!platforms_.Size())
         {
             errorMsg = "Platform not specified";
             return false;
         }
 
+        if (!configurations_.Size())
+        {
+            errorMsg = "configuration not specified";
+            return false;
+        }
+
+
         return true;
     }
-	else if (command_ == "genresources")
-	{
-		projectPath_ = startIndex + 2 < arguments.Size() ? arguments[startIndex + 2] : String::EMPTY;
-		platform_ = startIndex + 3 < arguments.Size() ? arguments[startIndex + 3] : String::EMPTY;
-		requiresProjectLoad_ = true;
-	}
+    else if (command_ == "genresources")
+    {
+        projectPath_ = startIndex + 2 < arguments.Size() ? arguments[startIndex + 2] : String::EMPTY;
+        requiresProjectLoad_ = true;
+
+        if (!platforms_.Size())
+        {
+            errorMsg = "Platform not specified";
+            return false;
+        }
+
+    }
     else
     {
         errorMsg = "Unknown net command";
@@ -135,45 +171,43 @@ void NETCmd::Run()
 {
     if (command_ == "compile")
     {
-		
-		FileSystem* fileSystem = GetSubsystem<FileSystem>();
-
+        
         NETBuildSystem* buildSystem = new NETBuildSystem(context_);
         context_->RegisterSubsystem(buildSystem);
 
-		NETBuild* build = 0;
+        NETBuild* build = 0;
 
-		String solutionPath;
-		String fileName;
-		String ext;
+        String solutionPath;
+        String fileName;
+        String ext;
 
-		// detect project        
-		SplitPath(solutionPath_, solutionPath, fileName, ext);
+        // detect project        
+        SplitPath(solutionPath_, solutionPath, fileName, ext);
 
-		if (ext == ".atomic")
-		{
-			SharedPtr<NETProjectGen> gen(new NETProjectGen(context_));
+        if (ext == ".atomic")
+        {
+            SharedPtr<NETProjectGen> gen(new NETProjectGen(context_));
 
-			if (!gen->LoadAtomicProject(solutionPath_))
-			{
-				Error(ToString("NETProjectGen: Error loading project (%s)", solutionPath.CString()));
-				Finished();
-				return;
-			}
+            if (!gen->LoadAtomicProject(solutionPath_))
+            {
+                Error(ToString("NETProjectGen: Error loading project (%s)", solutionPath.CString()));
+                Finished();
+                return;
+            }
 
-			if (!gen->Generate())
-			{
-				Error(ToString("NETProjectGen: Error generating project (%s)", solutionPath.CString()));
-				Finished();
-				return;
-			}
+            if (!gen->Generate())
+            {
+                Error(ToString("NETProjectGen: Error generating project (%s)", solutionPath.CString()));
+                Finished();
+                return;
+            }
 
-			solutionPath_ = solutionPath + "/AtomicNET/Solution/" + gen->GetProjectSettings()->GetName() + ".sln";
+            solutionPath_ = solutionPath + "/AtomicNET/Solution/" + gen->GetProjectSettings()->GetName() + ".sln";
 
-		}
+        }
 
-		// json project file
-		build = buildSystem->Build(solutionPath_, platform_, configuration_);
+        // json project file
+        build = buildSystem->Build(solutionPath_, platforms_, configurations_);
 
         if (!build)
         {
@@ -185,39 +219,39 @@ void NETCmd::Run()
         build->SubscribeToEvent(E_NETBUILDRESULT, ATOMIC_HANDLER(NETCmd, HandleNETBuildResult));
 
     }
-	else if (command_ == "genresources")
-	{
-		BuildSystem* buildSystem = GetSubsystem<BuildSystem>();
-		ToolSystem* toolSystem = GetSubsystem<ToolSystem>();
-		Project* project = toolSystem->GetProject();
-
-		if (!project)
-		{
-			Error("Unable to get project");
-			Finished();
-			return;
-		}
-
-		buildSystem->SetBuildPath(project->GetProjectPath() + "AtomicNET/Resources/");
-
-		Platform* platform = toolSystem->GetPlatformByName(platform_);
-
-		if (!platform)
-		{
-			Error(ToString("Unknown platform %s", platform_.CString()));
-			Finished();
-			return;
-		}
-
-		BuildBase* buildBase = platform->NewBuild(project);
-		buildBase->SetResourcesOnly(true);
-		buildBase->SetVerbose(true);
-		buildSystem->QueueBuild(buildBase);
-		buildSystem->StartNextBuild();
-
-		Finished();
-		return;
-	}
+    else if (command_ == "genresources")
+    {
+        BuildSystem* buildSystem = GetSubsystem<BuildSystem>();
+        ToolSystem* toolSystem = GetSubsystem<ToolSystem>();
+        Project* project = toolSystem->GetProject();
+
+        if (!project)
+        {
+            Error("Unable to get project");
+            Finished();
+            return;
+        }
+
+        buildSystem->SetBuildPath(project->GetProjectPath() + "AtomicNET/Resources/");
+
+        Platform* platform = toolSystem->GetPlatformByName(platforms_[0]);
+
+        if (!platform)
+        {
+            Error(ToString("Unknown platform %s", platforms_[0].CString()));
+            Finished();
+            return;
+        }
+
+        BuildBase* buildBase = platform->NewBuild(project);
+        buildBase->SetResourcesOnly(true);
+        buildBase->SetVerbose(true);
+        buildSystem->QueueBuild(buildBase);
+        buildSystem->StartNextBuild();
+
+        Finished();
+        return;
+    }
 
 }
 

+ 4 - 4
Source/ToolCore/Command/NETCmd.h

@@ -48,7 +48,7 @@ public:
 
     bool RequiresProjectLoad() { return requiresProjectLoad_; }
 
-	const String& GetProjectPath() const { return projectPath_; }
+    const String& GetProjectPath() const { return projectPath_; }
 
 private:
 
@@ -64,10 +64,10 @@ private:
 
     // compile
     String solutionPath_;
-    String platform_;
-    String configuration_;
+    StringVector platforms_;
+    StringVector configurations_;
 
-	bool requiresProjectLoad_;
+    bool requiresProjectLoad_;
 
     WeakPtr<AtomicNETService> netService_;
 

+ 15 - 15
Source/ToolCore/JSBind/CSharp/CSFunctionWriter.cpp

@@ -471,7 +471,7 @@ void CSFunctionWriter::GenManagedFunctionParameters(String& sig)
     {
         for (unsigned int i = 0; i < parameters.Size(); i++)
         {
-			bool isStruct = false;
+            bool isStruct = false;
             JSBFunctionType* ptype = parameters.At(i);
 
             // ignore "Context" parameters
@@ -485,23 +485,23 @@ void CSFunctionWriter::GenManagedFunctionParameters(String& sig)
                     continue;
                 }
 
-				// TODO: we should have a better system for struct type in general
-				// This number array is really for JS
-				if (klass->IsNumberArray())
-				{
-					isStruct = true;
-				}
+                // TODO: we should have a better system for struct type in general
+                // This number array is really for JS
+                if (klass->IsNumberArray())
+                {
+                    isStruct = true;
+                }
             }
 
-			String managedTypeString = CSTypeHelper::GetManagedTypeString(ptype);
+            String managedTypeString = CSTypeHelper::GetManagedTypeString(ptype);
 
-			if (!ptype->isConst_ && (ptype->isReference_ && isStruct))
-			{
-				// pass by reference
-				managedTypeString = "ref " + managedTypeString;
-			}
+            if (!ptype->isConst_ && (ptype->isReference_ && isStruct))
+            {
+                // pass by reference
+                managedTypeString = "ref " + managedTypeString;
+            }
 
-			sig += managedTypeString;
+            sig += managedTypeString;
 
             String init = ptype->initializer_;
 
@@ -560,7 +560,7 @@ void CSFunctionWriter::WriteManagedConstructor(String& source)
 
     Indent();
 
-	source += IndentLine(ToString("var classType = typeof(%s);\n", klass->GetName().CString()));
+    source += IndentLine(ToString("var classType = typeof(%s);\n", klass->GetName().CString()));
     source += IndentLine("var thisType = this.GetType();\n");
     source += IndentLine("var thisTypeIsNative = NativeCore.IsNativeType(thisType);\n");    
     source += IndentLine("var nativeAncsestorType = NativeCore.GetNativeAncestorType(thisType);\n");

+ 27 - 27
Source/ToolCore/JSBind/CSharp/CSModuleWriter.cpp

@@ -102,12 +102,12 @@ void CSModuleWriter::GenerateNativeSource()
 {
     String source = "// This file was autogenerated by JSBind, changes will be lost\n";
 
-	String moduleGuard = module_->GetModuleDefineGuard();
+    String moduleGuard = module_->GetModuleDefineGuard();
 
-	if (moduleGuard.Length())
-	{
-		source += ToString("\n%s\n", moduleGuard.CString());
-	}
+    if (moduleGuard.Length())
+    {
+        source += ToString("\n%s\n", moduleGuard.CString());
+    }
 
     source += "#ifdef ATOMIC_PLATFORM_WINDOWS\n";
 
@@ -147,20 +147,20 @@ void CSModuleWriter::GenerateNativeSource()
     for (unsigned i = 0; i < classes.Size(); i++)
     {
 
-		String classGuard = module_->GetClassDefineGuard(classes[i]->GetNativeName());
+        String classGuard = module_->GetClassDefineGuard(classes[i]->GetNativeName());
 
-		if (classGuard.Length())
-		{
-			source += ToString("\n%s\n\n", classGuard.CString());
-		}
+        if (classGuard.Length())
+        {
+            source += ToString("\n%s\n\n", classGuard.CString());
+        }
 
         CSClassWriter clsWriter(classes[i]);
         clsWriter.GenerateNativeSource(source);
 
-		if (classGuard.Length())
-		{
-			source += "#endif\n\n";
-		}
+        if (classGuard.Length())
+        {
+            source += "#endif\n\n";
+        }
 
     }
 
@@ -174,10 +174,10 @@ void CSModuleWriter::GenerateNativeSource()
         source += "#endif //ATOMIC_3D\n";
     }
 
-	if (moduleGuard.Length())
-	{
-		source += "\n#endif\n";
-	}
+    if (moduleGuard.Length())
+    {
+        source += "\n#endif\n";
+    }
 
     JSBind* jsbind = module_->GetSubsystem<JSBind>();
 
@@ -416,22 +416,22 @@ void CSModuleWriter::GenerateManagedModuleClass(String& sourceOut)
 
         const char* className = klass->GetName().CString();
 
-		String classGuard = module_->GetClassDefineGuard(classes[i]->GetNativeName(), "csharp");
+        String classGuard = module_->GetClassDefineGuard(classes[i]->GetNativeName(), "csharp");
 
-		if (classGuard.Length())
-		{
-			source += ToString("\n%s\n", classGuard.CString());
-		}
+        if (classGuard.Length())
+        {
+            source += ToString("\n%s\n", classGuard.CString());
+        }
 
         line = ToString("new NativeType(%s.csb_%s_%s_GetClassIDStatic (), ", className, package->GetName().CString(), className);
         line += ToString("typeof(%s), (IntPtr x) => { return new %s (x); } );\n",className, className);
 
         source += IndentLine(line);
 
-		if (classGuard.Length())
-		{
-			source += ToString("#endif\n", classGuard.CString());
-		}
+        if (classGuard.Length())
+        {
+            source += ToString("#endif\n", classGuard.CString());
+        }
 
 
     }

+ 9 - 9
Source/ToolCore/JSBind/CSharp/CSPackageWriter.cpp

@@ -171,12 +171,12 @@ void CSPackageWriter::GenerateNativeSource()
 
     String source = "// This file was autogenerated by AtomicTool, changes will be lost\n\n";
 
-	String defineGuard = package_->GetPlatformDefineGuard();
+    String defineGuard = package_->GetPlatformDefineGuard();
 
-	if (defineGuard.Length())
-	{
-		source += ToString("%s\n\n", defineGuard.CString());
-	}
+    if (defineGuard.Length())
+    {
+        source += ToString("%s\n\n", defineGuard.CString());
+    }
 
     const char* packageName = package_->name_.CString();
 
@@ -192,10 +192,10 @@ void CSPackageWriter::GenerateNativeSource()
     // end of namespace
     source += "\n}\n";
 
-	if (defineGuard.Length())
-	{
-		source += "\n#endif\n";
-	}
+    if (defineGuard.Length())
+    {
+        source += "\n#endif\n";
+    }
 
     JSBind* jsbind = package_->GetSubsystem<JSBind>();
 

+ 2 - 2
Source/ToolCore/JSBind/JSBEnum.cpp

@@ -54,7 +54,7 @@ void JSBEnum::Preprocess()
 
     JSBind* jsbind = GetSubsystem<JSBind>();
 
-	// FIXME: This is going to need to be hand rolled with unified script bindings
+    // FIXME: This is going to need to be hand rolled with unified script bindings
     if (name_ == "TextureUnit")
     {
         values_.Clear();
@@ -69,7 +69,7 @@ void JSBEnum::Preprocess()
 
         // String platform = jsbind->GetPlatform();
 
-		bool mobile = true; //  platform == "WEB" || platform == "ANDROID" || platform == "IOS";
+        bool mobile = true; //  platform == "WEB" || platform == "ANDROID" || platform == "IOS";
 
         if (mobile)
         {

+ 158 - 158
Source/ToolCore/JSBind/JSBModule.cpp

@@ -92,7 +92,7 @@ void JSBModule::VisitHeaders()
 
     ProcessOverloads();
     ProcessExcludes();
-	ProcessClassExcludes();
+    ProcessClassExcludes();
     ProcessTypeScriptDecl();
     ProcessHaxeDecl();
 }
@@ -238,28 +238,28 @@ void JSBModule::ProcessClassExcludes()
     JSONValue excludes = root.Get("classExcludes");
 
     if (excludes.IsObject())
-	{
-		Vector<String> classes = excludes.GetObject().Keys();
+    {
+        Vector<String> classes = excludes.GetObject().Keys();
 
-		for (unsigned i = 0; i < classes.Size(); i++)
-		{
-			const String& classname = classes[i];
+        for (unsigned i = 0; i < classes.Size(); i++)
+        {
+            const String& classname = classes[i];
 
-			if (!classExcludes_.Contains(classname))
-			{
-				classExcludes_[classname] = Vector<String>();
-			}
+            if (!classExcludes_.Contains(classname))
+            {
+                classExcludes_[classname] = Vector<String>();
+            }
 
-			JSONArray platforms = excludes[classname].GetArray();
+            JSONArray platforms = excludes[classname].GetArray();
 
-			for (unsigned j = 0; j < platforms.Size(); j++)
-			{
-				classExcludes_[classname].Push(platforms[j].GetString());
-			}
+            for (unsigned j = 0; j < platforms.Size(); j++)
+            {
+                classExcludes_[classname].Push(platforms[j].GetString());
+            }
 
-		}
+        }
 
-	}
+    }
 
 }
 
@@ -420,151 +420,151 @@ JSBEnum* JSBModule::GetEnum(const String& name)
 
 String JSBModule::GetClassDefineGuard(const String& name, const String& language) const
 {
-	StringVector platforms;
-
-	if (!classExcludes_.TryGetValue(name, platforms) || !platforms.Size())
-		return String::EMPTY;
-
-	Vector<String> defines;
-
-	for (unsigned i = 0; i < platforms.Size(); i++)
-	{
-		String platform = platforms[i].ToLower();
-
-		if (platform == "windows")
-		{
-			if (language == "csharp")
-			{
-				if (!defines.Contains("!ATOMIC_DESKTOP"))
-					defines.Push("!ATOMIC_DESKTOP");
-			}
-			else
-			{
-				defines.Push("!defined(ATOMIC_PLATFORM_WINDOWS)");
-			}
-			
-		}
-		else if (platform == "macosx")
-		{
-			if (language == "csharp")
-			{
-				if (!defines.Contains("!ATOMIC_DESKTOP"))
-					defines.Push("!ATOMIC_DESKTOP");
-			}
-			else
-			{
-				defines.Push("!defined(ATOMIC_PLATFORM_OSX)");
-			}
-		}
-		else if (platform == "linux")
-		{
-			if (language == "csharp")
-			{
-				if (!defines.Contains("!ATOMIC_DESKTOP"))
-					defines.Push("!ATOMIC_DESKTOP");
-			}
-			else
-			{
-				defines.Push("!defined(ATOMIC_PLATFORM_LINUX)");
-			}
-		}
-		else if (platform == "android")
-		{
-			if (language == "csharp")
-			{
-				defines.Push("!ATOMIC_ANDROID");
-			}
-			else
-			{
-				defines.Push("!defined(ATOMIC_PLATFORM_ANDROID)");
-			}
-		}
-		else if (platform == "ios")
-		{
-			if (language == "csharp")
-			{
-				defines.Push("!ATOMIC_IOS");
-			}
-			else
-			{
-				defines.Push("!defined(ATOMIC_PLATFORM_IOS)");
-			}
-		}
-		else if (platform == "web")
-		{
-			if (language == "csharp")
-			{
-				defines.Push("!ATOMIC_WEB");
-			}
-			else
-			{
-				defines.Push("!defined(ATOMIC_PLATFORM_WEB)");
-			}
-		}
-		else
-		{
-			ATOMIC_LOGERRORF("Unknown package platform: %s", platform.CString());
-		}
-	}
-
-	if (!defines.Size())
-		return String::EMPTY;
-
-	String defineString = "#if " + String::Joined(defines, " && ");
-
-	return defineString;
+    StringVector platforms;
+
+    if (!classExcludes_.TryGetValue(name, platforms) || !platforms.Size())
+        return String::EMPTY;
+
+    Vector<String> defines;
+
+    for (unsigned i = 0; i < platforms.Size(); i++)
+    {
+        String platform = platforms[i].ToLower();
+
+        if (platform == "windows")
+        {
+            if (language == "csharp")
+            {
+                if (!defines.Contains("!ATOMIC_DESKTOP"))
+                    defines.Push("!ATOMIC_DESKTOP");
+            }
+            else
+            {
+                defines.Push("!defined(ATOMIC_PLATFORM_WINDOWS)");
+            }
+            
+        }
+        else if (platform == "macosx")
+        {
+            if (language == "csharp")
+            {
+                if (!defines.Contains("!ATOMIC_DESKTOP"))
+                    defines.Push("!ATOMIC_DESKTOP");
+            }
+            else
+            {
+                defines.Push("!defined(ATOMIC_PLATFORM_OSX)");
+            }
+        }
+        else if (platform == "linux")
+        {
+            if (language == "csharp")
+            {
+                if (!defines.Contains("!ATOMIC_DESKTOP"))
+                    defines.Push("!ATOMIC_DESKTOP");
+            }
+            else
+            {
+                defines.Push("!defined(ATOMIC_PLATFORM_LINUX)");
+            }
+        }
+        else if (platform == "android")
+        {
+            if (language == "csharp")
+            {
+                defines.Push("!ATOMIC_ANDROID");
+            }
+            else
+            {
+                defines.Push("!defined(ATOMIC_PLATFORM_ANDROID)");
+            }
+        }
+        else if (platform == "ios")
+        {
+            if (language == "csharp")
+            {
+                defines.Push("!ATOMIC_IOS");
+            }
+            else
+            {
+                defines.Push("!defined(ATOMIC_PLATFORM_IOS)");
+            }
+        }
+        else if (platform == "web")
+        {
+            if (language == "csharp")
+            {
+                defines.Push("!ATOMIC_WEB");
+            }
+            else
+            {
+                defines.Push("!defined(ATOMIC_PLATFORM_WEB)");
+            }
+        }
+        else
+        {
+            ATOMIC_LOGERRORF("Unknown package platform: %s", platform.CString());
+        }
+    }
+
+    if (!defines.Size())
+        return String::EMPTY;
+
+    String defineString = "#if " + String::Joined(defines, " && ");
+
+    return defineString;
 
 }
 
 String JSBModule::GetModuleDefineGuard() const
 {
-	// platform -> vector of modules
-	const HashMap<String, Vector<String>>& platformExcludes = package_->GetModuleExcludes();
-	HashMap<String, Vector<String>>::ConstIterator itr = platformExcludes.Begin();
-
-	Vector<String> defines;
-
-	while (itr != platformExcludes.End())
-	{
-		const String& platform = itr->first_;
-		const Vector<String>& modules = itr->second_;
-
-		for (unsigned i = 0; i < modules.Size(); i++)
-		{
-			if (modules[i].ToLower() == name_.ToLower())
-			{
-				if (platform.ToLower() == "windows")
-					defines.Push("!defined(ATOMIC_PLATFORM_WINDOWS)");
-				else if (platform.ToLower() == "macosx")
-					defines.Push("!defined(ATOMIC_PLATFORM_OSX)");
-				else if (platform.ToLower() == "linux")
-					defines.Push("!defined(ATOMIC_PLATFORM_LINUX)");
-				else if (platform.ToLower() == "android")
-					defines.Push("!defined(ATOMIC_PLATFORM_ANDROID)");
-				else if (platform.ToLower() == "ios")
-					defines.Push("!defined(ATOMIC_PLATFORM_IOS)");
-				else if (platform.ToLower() == "web")
-					defines.Push("!defined(ATOMIC_PLATFORM_WEB)");
-				else
-				{
-					ATOMIC_LOGERRORF("Unknown package platform: %s", platform.CString());
-				}
-
-				break;
-			}
-
-		}
-	
-		itr++;
-	}
-	
-	if (!defines.Size())
-		return String::EMPTY;
-
-	String defineString = "#if " + String::Joined(defines, " && ");
-
-	return defineString;
-	
+    // platform -> vector of modules
+    const HashMap<String, Vector<String>>& platformExcludes = package_->GetModuleExcludes();
+    HashMap<String, Vector<String>>::ConstIterator itr = platformExcludes.Begin();
+
+    Vector<String> defines;
+
+    while (itr != platformExcludes.End())
+    {
+        const String& platform = itr->first_;
+        const Vector<String>& modules = itr->second_;
+
+        for (unsigned i = 0; i < modules.Size(); i++)
+        {
+            if (modules[i].ToLower() == name_.ToLower())
+            {
+                if (platform.ToLower() == "windows")
+                    defines.Push("!defined(ATOMIC_PLATFORM_WINDOWS)");
+                else if (platform.ToLower() == "macosx")
+                    defines.Push("!defined(ATOMIC_PLATFORM_OSX)");
+                else if (platform.ToLower() == "linux")
+                    defines.Push("!defined(ATOMIC_PLATFORM_LINUX)");
+                else if (platform.ToLower() == "android")
+                    defines.Push("!defined(ATOMIC_PLATFORM_ANDROID)");
+                else if (platform.ToLower() == "ios")
+                    defines.Push("!defined(ATOMIC_PLATFORM_IOS)");
+                else if (platform.ToLower() == "web")
+                    defines.Push("!defined(ATOMIC_PLATFORM_WEB)");
+                else
+                {
+                    ATOMIC_LOGERRORF("Unknown package platform: %s", platform.CString());
+                }
+
+                break;
+            }
+
+        }
+    
+        itr++;
+    }
+    
+    if (!defines.Size())
+        return String::EMPTY;
+
+    String defineString = "#if " + String::Joined(defines, " && ");
+
+    return defineString;
+    
 }
 
 bool JSBModule::ContainsConstant(const String& constantName)
@@ -595,7 +595,7 @@ bool JSBModule::Load(const String& jsonFilename)
 {    
     ATOMIC_LOGINFOF("Loading Module: %s", jsonFilename.CString());
 
-	JSBind* jsbind = GetSubsystem<JSBind>();
+    JSBind* jsbind = GetSubsystem<JSBind>();
 
     SharedPtr<File> jsonFile(new File(context_, jsonFilename));
 

+ 6 - 6
Source/ToolCore/JSBind/JSBModule.h

@@ -88,17 +88,17 @@ public:
     void SetDotNetModule(bool value) { dotNetModule_ = value; }
     bool GetDotNetModule() { return dotNetModule_; }
 
-	/// Define guard for specific module code
-	String GetModuleDefineGuard() const;
+    /// Define guard for specific module code
+    String GetModuleDefineGuard() const;
 
-	/// Define guard for specific module code
-	String GetClassDefineGuard(const String& name, const String& language = String::EMPTY) const;
+    /// Define guard for specific module code
+    String GetClassDefineGuard(const String& name, const String& language = String::EMPTY) const;
 
 private:
 
     void ProcessOverloads();
     void ProcessExcludes();
-	void ProcessClassExcludes();
+    void ProcessClassExcludes();
     void ProcessTypeScriptDecl();
     void ProcessHaxeDecl();
 
@@ -128,7 +128,7 @@ private:
 
     SharedPtr<JSONFile> moduleJSON_;
 
-	HashMap<String, Vector<String>> classExcludes_;
+    HashMap<String, Vector<String>> classExcludes_;
 
     bool dotNetModule_;
 

+ 38 - 38
Source/ToolCore/JSBind/JSBPackage.cpp

@@ -201,12 +201,12 @@ bool JSBPackage::Load(const String& packageFolder)
 
     }
 
-	JSONArray jplatforms = root["platforms"].GetArray();
+    JSONArray jplatforms = root["platforms"].GetArray();
 
-	for (unsigned i = 0; i < jplatforms.Size(); i++)
-	{
-		platforms_.Push(jplatforms[i].GetString());
-	}
+    for (unsigned i = 0; i < jplatforms.Size(); i++)
+    {
+        platforms_.Push(jplatforms[i].GetString());
+    }
 
     JSONValue jmodulesExclude = root.Get("moduleExclude");
 
@@ -309,39 +309,39 @@ bool JSBPackage::Load(const String& packageFolder)
 
 String JSBPackage::GetPlatformDefineGuard() const
 {
-	if (!platforms_.Size())
-		return String::EMPTY;
-
-	StringVector defines;
-
-	for (unsigned i = 0; i < platforms_.Size(); i++)
-	{
-		const String& platform = platforms_[i];
-
-		if (platform.ToLower() == "windows")
-			defines.Push("defined(ATOMIC_PLATFORM_WINDOWS)");
-		else if (platform.ToLower() == "macosx")
-			defines.Push("defined(ATOMIC_PLATFORM_OSX)");
-		else if (platform.ToLower() == "linux")
-			defines.Push("defined(ATOMIC_PLATFORM_LINUX)");
-		else if (platform.ToLower() == "android")
-			defines.Push("defined(ATOMIC_PLATFORM_ANDROID)");
-		else if (platform.ToLower() == "ios")
-			defines.Push("defined(ATOMIC_PLATFORM_IOS)");
-		else if (platform.ToLower() == "web")
-			defines.Push("defined(ATOMIC_PLATFORM_WEB)");
-		else
-		{
-			ATOMIC_LOGERRORF("Unknown package platform: %s", platform.CString());
-		}
-	}
-
-	if (!defines.Size())
-		return String::EMPTY;
-
-	String defineString = "#if " + String::Joined(defines, " || ");
-
-	return defineString;
+    if (!platforms_.Size())
+        return String::EMPTY;
+
+    StringVector defines;
+
+    for (unsigned i = 0; i < platforms_.Size(); i++)
+    {
+        const String& platform = platforms_[i];
+
+        if (platform.ToLower() == "windows")
+            defines.Push("defined(ATOMIC_PLATFORM_WINDOWS)");
+        else if (platform.ToLower() == "macosx")
+            defines.Push("defined(ATOMIC_PLATFORM_OSX)");
+        else if (platform.ToLower() == "linux")
+            defines.Push("defined(ATOMIC_PLATFORM_LINUX)");
+        else if (platform.ToLower() == "android")
+            defines.Push("defined(ATOMIC_PLATFORM_ANDROID)");
+        else if (platform.ToLower() == "ios")
+            defines.Push("defined(ATOMIC_PLATFORM_IOS)");
+        else if (platform.ToLower() == "web")
+            defines.Push("defined(ATOMIC_PLATFORM_WEB)");
+        else
+        {
+            ATOMIC_LOGERRORF("Unknown package platform: %s", platform.CString());
+        }
+    }
+
+    if (!defines.Size())
+        return String::EMPTY;
+
+    String defineString = "#if " + String::Joined(defines, " || ");
+
+    return defineString;
 
 }
 

+ 5 - 5
Source/ToolCore/JSBind/JSBPackage.h

@@ -87,11 +87,11 @@ public:
 
     void GenerateSource(JSBPackageWriter& packageWriter);
 
-	/// Define guard for the package as a whole
-	String GetPlatformDefineGuard() const;
+    /// Define guard for the package as a whole
+    String GetPlatformDefineGuard() const;
 
-	const Vector<String>& GetPlatforms() const { return platforms_; }
-	const HashMap<String, Vector<String>>& GetModuleExcludes() const { return moduleExcludes_; }
+    const Vector<String>& GetPlatforms() const { return platforms_; }
+    const HashMap<String, Vector<String>>& GetModuleExcludes() const { return moduleExcludes_; }
 
 private:
 
@@ -103,7 +103,7 @@ private:
 
     Vector<SharedPtr<JSBPackage> > dependencies_;
 
-	Vector<String> platforms_;
+    Vector<String> platforms_;
     HashMap<String, Vector<String>> moduleExcludes_;
 
     Vector<SharedPtr<JSBModule> > modules_;

+ 9 - 9
Source/ToolCore/JSBind/JavaScript/JSModuleWriter.cpp

@@ -263,12 +263,12 @@ void JSModuleWriter::GenerateSource()
 {
     String source = "// This file was autogenerated by JSBind, changes will be lost\n";
 
-	String moduleGuard = module_->GetModuleDefineGuard();
+    String moduleGuard = module_->GetModuleDefineGuard();
 
-	if (moduleGuard.Length())
-	{
-		source += ToString("\n%s\n", moduleGuard.CString());
-	}
+    if (moduleGuard.Length())
+    {
+        source += ToString("\n%s\n", moduleGuard.CString());
+    }
 
     source += "#ifdef ATOMIC_PLATFORM_WINDOWS\n";
 
@@ -333,10 +333,10 @@ void JSModuleWriter::GenerateSource()
     }
 
 
-	if (moduleGuard.Length())
-	{
-		source += ToString("\n#endif\n", moduleGuard.CString());
-	}
+    if (moduleGuard.Length())
+    {
+        source += ToString("\n#endif\n", moduleGuard.CString());
+    }
 
     JSBind* jsbind = module_->GetSubsystem<JSBind>();
 

+ 49 - 49
Source/ToolCore/JSBind/JavaScript/JSPackageWriter.cpp

@@ -69,12 +69,12 @@ void JSPackageWriter::WriteProtoTypeRecursive(String &source, JSBClass* klass,
     {
         JSBModule* module = klass->GetModule();
 
-		String moduleGuard = module->GetModuleDefineGuard();
+        String moduleGuard = module->GetModuleDefineGuard();
 
-		if (moduleGuard.Length())
-		{
-			source += ToString("\n%s\n", moduleGuard.CString());
-		}
+        if (moduleGuard.Length())
+        {
+            source += ToString("\n%s\n", moduleGuard.CString());
+        }
 
         if (module->Requires("3D"))
             source += "\n#ifdef ATOMIC_3D\n";
@@ -90,10 +90,10 @@ void JSPackageWriter::WriteProtoTypeRecursive(String &source, JSBClass* klass,
         if (module->Requires("3D"))
             source += "#endif\n\n";
 
-		if (moduleGuard.Length())
-		{
-			source += ToString("\n#endif\n", moduleGuard.CString());
-		}
+        if (moduleGuard.Length())
+        {
+            source += ToString("\n#endif\n", moduleGuard.CString());
+        }
 
     }
 
@@ -117,12 +117,12 @@ void JSPackageWriter::GenerateSource()
 {
     String source = "// This file was autogenerated by JSBind, changes will be lost\n\n";
 
-	String defineGuard = package_->GetPlatformDefineGuard();
+    String defineGuard = package_->GetPlatformDefineGuard();
 
-	if (defineGuard.Length())
-	{
-		source += ToString("%s\n\n", defineGuard.CString());		
-	}
+    if (defineGuard.Length())
+    {
+        source += ToString("%s\n\n", defineGuard.CString());        
+    }
 
     source += "#include <Duktape/duktape.h>\n";
     source += "#include <AtomicJS/Javascript/JSVM.h>\n";
@@ -139,22 +139,22 @@ void JSPackageWriter::GenerateSource()
         if (module->GetDotNetModule())
             continue;
 
-		String moduleGuard = module->GetModuleDefineGuard();
+        String moduleGuard = module->GetModuleDefineGuard();
 
-		if (moduleGuard.Length())
-		{
-			source += ToString("\n%s\n", moduleGuard.CString());
-		}
+        if (moduleGuard.Length())
+        {
+            source += ToString("\n%s\n", moduleGuard.CString());
+        }
 
         String moduleLower = module->GetName().ToLower();
 
         source.AppendWithFormat("\nextern void jsb_package_%s_preinit_%s (JSVM* vm);", packageLower.CString(), moduleLower.CString());
         source.AppendWithFormat("\nextern void jsb_package_%s_init_%s (JSVM* vm);", packageLower.CString(), moduleLower.CString());
 
-		if (moduleGuard.Length())
-		{
-			source += ToString("\n#endif\n", moduleGuard.CString());
-		}
+        if (moduleGuard.Length())
+        {
+            source += ToString("\n#endif\n", moduleGuard.CString());
+        }
 
     }
 
@@ -182,12 +182,12 @@ void JSPackageWriter::GenerateSource()
         if (module->GetDotNetModule())
             continue;
 
-		String moduleGuard = module->GetModuleDefineGuard();
+        String moduleGuard = module->GetModuleDefineGuard();
 
-		if (moduleGuard.Length())
-		{
-			source += ToString("\n%s\n", moduleGuard.CString());
-		}
+        if (moduleGuard.Length())
+        {
+            source += ToString("\n%s\n", moduleGuard.CString());
+        }
 
         if (module->Requires("3D"))
             source += "\n#ifdef ATOMIC_3D";
@@ -199,10 +199,10 @@ void JSPackageWriter::GenerateSource()
         if (module->Requires("3D"))
             source += "\n#endif //ATOMIC_3D\n";
 
-		if (moduleGuard.Length())
-		{
-			source += ToString("\n#endif\n", moduleGuard.CString());
-		}
+        if (moduleGuard.Length())
+        {
+            source += ToString("\n#endif\n", moduleGuard.CString());
+        }
 
     }
 
@@ -223,27 +223,27 @@ void JSPackageWriter::GenerateSource()
 
         String moduleLower = module->GetName().ToLower();
 
-		String moduleGuard = module->GetModuleDefineGuard();
+        String moduleGuard = module->GetModuleDefineGuard();
 
-		if (moduleGuard.Length())
-		{
-			source += ToString("\n%s\n", moduleGuard.CString());
-		}
+        if (moduleGuard.Length())
+        {
+            source += ToString("\n%s\n", moduleGuard.CString());
+        }
 
         if (module->Requires("3D"))
             source += "\n#ifdef ATOMIC_3D";
 
         source.AppendWithFormat("\n   jsb_package_%s_init_%s(vm);", packageLower.CString(), moduleLower.CString());
         
-		if (module->Requires("3D"))
-		{
-			source += "\n#endif //ATOMIC_3D\n";
-		}
+        if (module->Requires("3D"))
+        {
+            source += "\n#endif //ATOMIC_3D\n";
+        }
 
-		if (moduleGuard.Length())
-		{
-			source += ToString("\n#endif\n", moduleGuard.CString());
-		}
+        if (moduleGuard.Length())
+        {
+            source += ToString("\n#endif\n", moduleGuard.CString());
+        }
 
     }
 
@@ -252,10 +252,10 @@ void JSPackageWriter::GenerateSource()
     // end Atomic namespace
     source += "\n}\n";
 
-	if (defineGuard.Length())
-	{
-		source += "\n#endif\n";
-	}
+    if (defineGuard.Length())
+    {
+        source += "\n#endif\n";
+    }
 
     JSBind* jsbind = package_->GetSubsystem<JSBind>();
 

+ 4 - 4
Source/ToolCore/NETTools/AtomicNETService.cpp

@@ -59,16 +59,16 @@ namespace ToolCore
         args.Clear();
 
 #ifdef ATOMIC_DEBUG
-		String config = "Debug";
+        String config = "Debug";
 #else
-		String config = "Release";
+        String config = "Release";
 #endif
 
-		String netServiceFilename = tenv->GetAtomicNETRootDir() + config + "/AtomicNETService/AtomicNETService.exe";
+        String netServiceFilename = tenv->GetAtomicNETRootDir() + config + "/AtomicNETService/AtomicNETService.exe";
 
 #ifdef ATOMIC_PLATFORM_WINDOWS        
 
-		execPath = netServiceFilename;
+        execPath = netServiceFilename;
 
 #elif defined ATOMIC_PLATFORM_OSX
 

+ 78 - 34
Source/ToolCore/NETTools/NETBuildSystem.cpp

@@ -41,14 +41,23 @@
 namespace ToolCore
 {
 
-    NETBuild::NETBuild(Context* context, const String& solutionPath, const String& platform, const String& configuration) :
+    NETBuild::NETBuild(Context* context, const String& solutionPath, const StringVector& platforms, const StringVector& configurations) :
         Object(context),
         solutionPath_(solutionPath),
-        platform_(platform),
-        configuration_(configuration),
         status_(NETBUILD_PENDING)
     {
+        for (unsigned i = 0; i < platforms.Size() ; i++)
+        {
+            platforms_.Push(platforms[i].ToLower());
+        }
 
+        for (unsigned i = 0; i < configurations.Size() ; i++)
+        {
+            String config = configurations[i];
+            config.Replace("release", "Release");
+            config.Replace("debug", "Debug");
+            configurations_.Push(config);
+        }
     }
 
     NETBuildSystem::NETBuildSystem(Context* context) :
@@ -174,7 +183,7 @@ namespace ToolCore
             if (ext == ".sln")
             {
                 // TODO: handle projects that require nuget
-				requiresNuGet = false;
+                requiresNuGet = false;
 
                 if (!fileSystem->FileExists(solutionPath))
                 {
@@ -187,15 +196,8 @@ namespace ToolCore
             {
                 SharedPtr<NETProjectGen> gen(new NETProjectGen(context_));
 
-				StringVector platforms;
-				platforms.Push("desktop");
-
-				if (curBuild_->platform_.ToLower() == "android")
-				{
-					platforms.Push("android");
-				}
-
-				gen->SetSupportedPlatforms(platforms);
+                gen->SetSupportedPlatforms(curBuild_->platforms_);
+                gen->SetRewriteSolution(true);
 
                 if (!gen->LoadJSONProject(solutionPath))
                 {
@@ -229,7 +231,53 @@ namespace ToolCore
                 return;
             }
 
-            const String configuration = curBuild_->configuration_;
+            StringVector stringVector;
+            String platforms;
+            String configs;
+
+            for (unsigned i = 0; i < curBuild_->configurations_.Size(); i++)
+            {
+                stringVector.Push(ToString("/p:Configuration=%s", curBuild_->configurations_[i].CString()));
+            }
+
+            configs = String::Joined(stringVector, " ");
+            stringVector.Clear();
+
+            for (unsigned i = 0; i < curBuild_->platforms_.Size(); i++)
+            {
+                // map platform
+                String platform = curBuild_->platforms_[i];
+
+                if (platform == "desktop" || platform == "android")
+                {
+                    platform = "\"Any CPU\"";
+                }
+                else if (platform == "ios")
+                {
+
+                    platform = "\"Any CPU\"";
+                    // TODO
+                    // platform = "iPhone";
+                }
+                else
+                {
+                    ATOMIC_LOGERRORF("Unknown platform: %s, skipping", platform.CString());
+                    continue;
+                }
+
+                platform = ToString("/p:Platform=%s", platform.CString());
+
+                if (stringVector.Contains(platform))
+                {
+                    // This can happen when specifying Desktop + Android for example
+                    continue;
+                }
+
+                stringVector.Push(platform);
+            }
+
+            platforms = String::Joined(stringVector, " ");
+            stringVector.Clear();
 
             Vector<String> args;
 
@@ -258,7 +306,7 @@ namespace ToolCore
                 compile += ToString("&& \"%s\" restore \"%s\" ", nugetBinary.CString(), solutionPath.CString());
             }
 
-            compile += ToString("&& msbuild \"%s\" /p:Configuration=%s /p:Platform=\"Any CPU\"\"", solutionPath.CString(), configuration.CString());
+            compile += ToString("&& msbuild \"%s\" %s %s\"", solutionPath.CString(), platforms.CString(), configs.CString());
 
             args.Push(compile);
 
@@ -280,7 +328,7 @@ namespace ToolCore
 #endif
             }
 
-            compile += ToString("\"%s\" \"%s\" /p:Configuration=%s /p:Platform=\"Any CPU\"", xbuildBinary.CString(), solutionPath.CString(), configuration.CString());
+            compile += ToString("\"%s\" \"%s\" %s %s", xbuildBinary.CString(), solutionPath.CString(), platforms.CString(), configs.CString());
 
             args.Push(compile);
 
@@ -291,6 +339,8 @@ namespace ToolCore
             SubprocessSystem* subs = GetSubsystem<SubprocessSystem>();
             Subprocess* subprocess = nullptr;
 
+            ATOMIC_LOGINFOF("%s : %s", cmd.CString(), curBuild_->allArgs_.CString());
+
             try
             {
                 subprocess = subs->Launch(cmd, args, "");
@@ -316,7 +366,7 @@ namespace ToolCore
     }
 
 
-    NETBuild* NETBuildSystem::GetBuild(const String& solutionPath, const String& platform, const String& configuration)
+    NETBuild* NETBuildSystem::GetBuild(const String& solutionPath, const StringVector& platforms, const StringVector& configurations)
     {
         List<SharedPtr<NETBuild>>::ConstIterator itr = builds_.Begin();
 
@@ -324,7 +374,7 @@ namespace ToolCore
         {
             NETBuild* build = *itr;
 
-            if (build->solutionPath_ == solutionPath && build->platform_ == platform && build->configuration_ == configuration)
+            if (build->solutionPath_ == solutionPath && build->platforms_ == platforms && build->configurations_ == configurations)
                 return build;
 
             itr++;
@@ -336,26 +386,20 @@ namespace ToolCore
 
     NETBuild* NETBuildSystem::BuildAtomicProject(Project* project)
     {
-        String platform;
-        String configuration;
+        StringVector platforms;
+        StringVector configurations;
 
-#ifdef ATOMIC_PLATFORM_WINDOWS
-        platform = "WINDOWS";
-#elif ATOMIC_PLATFORM_OSX
-        platform = "MACOSX";
-#else
-        platform = "LINUX";
-#endif
+        platforms.Push("desktop");
 
 #ifdef ATOMIC_DEBUG
-        configuration = "Debug";
+        configurations.Push("Debug");
 #else
-        configuration = "Release";
+        configurations.Push("Release");
 #endif
 
-		String solutionPath = project->GetProjectPath() + "AtomicNET/Solution/" + project->GetProjectSettings()->GetName() + ".sln";
+        String solutionPath = project->GetProjectPath() + "AtomicNET/Solution/" + project->GetProjectSettings()->GetName() + ".sln";
 
-        NETBuild* build = Build(solutionPath, platform, configuration);
+        NETBuild* build = Build(solutionPath, platforms, configurations);
 
         if (build)
         {
@@ -385,7 +429,7 @@ namespace ToolCore
 
     }
 
-    NETBuild* NETBuildSystem::Build(const String& solutionPath, const String& platform, const String& configuration)
+    NETBuild* NETBuildSystem::Build(const String& solutionPath, const StringVector& platforms, const StringVector& configurations)
     {
 
         FileSystem* fileSystem = GetSubsystem<FileSystem>();
@@ -397,13 +441,13 @@ namespace ToolCore
         }
 
         // Get existing build
-        SharedPtr<NETBuild> build(GetBuild(solutionPath, platform, configuration));
+        SharedPtr<NETBuild> build(GetBuild(solutionPath, platforms, configurations));
 
         if (build.NotNull())
             return build;
 
         // Create a new build
-        build = new NETBuild(context_, solutionPath, platform, configuration);
+        build = new NETBuild(context_, solutionPath, platforms, configurations);
 
         builds_.Push(build);
 

+ 6 - 5
Source/ToolCore/NETTools/NETBuildSystem.h

@@ -58,14 +58,15 @@ namespace ToolCore
     
     public:
 
-        NETBuild(Context* context, const String& solutionPath, const String& platform, const String& configuration);
+        NETBuild(Context* context, const String& solutionPath, const StringVector& platforms, const StringVector& configurations);
         virtual ~NETBuild() {}
 
     private:
         /// .sln or .json configuration file
         String solutionPath_;
-        String configuration_;
-        String platform_;
+        StringVector configurations_;
+        StringVector platforms_;
+
         NETBuildStatus status_;
         String allArgs_;
         String output_;
@@ -85,7 +86,7 @@ namespace ToolCore
         virtual ~NETBuildSystem();
 
         /// Build either a .sln or .json configuration file
-        NETBuild* Build(const String& solutionPath, const String& platform, const String& configuration = "Release");
+        NETBuild* Build(const String& solutionPath, const StringVector &platforms, const StringVector &configurations);
 
         NETBuild* BuildAtomicProject(Project* project);
 
@@ -93,7 +94,7 @@ namespace ToolCore
 
         void CurrentBuildError(String errorText);
 
-        NETBuild* GetBuild(const String& solutionPath, const String& platform, const String& configuration);
+        NETBuild* GetBuild(const String& solutionPath, const StringVector& platforms, const StringVector& configurations);
 
         void HandleBuildAtomicProject(StringHash eventType, VariantMap& eventData);
         void HandleToolUpdate(StringHash eventType, VariantMap& eventData);

+ 1327 - 1193
Source/ToolCore/NETTools/NETProjectGen.cpp

@@ -38,373 +38,391 @@
 namespace ToolCore
 {
 
-	NETProjectBase::NETProjectBase(Context* context, NETProjectGen* projectGen) :
-		Object(context), xmlFile_(new XMLFile(context)), projectGen_(projectGen)
-	{
+    NETProjectBase::NETProjectBase(Context* context, NETProjectGen* projectGen) :
+        Object(context), xmlFile_(new XMLFile(context)), projectGen_(projectGen)
+    {
 
-	}
+    }
 
-	NETProjectBase::~NETProjectBase()
-	{
+    NETProjectBase::~NETProjectBase()
+    {
 
-	}
+    }
 
-	void NETProjectBase::ReplacePathStrings(String& path)
-	{
-		ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+    void NETProjectBase::ReplacePathStrings(String& path)
+    {
+        ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
 
-		String atomicRoot = tenv->GetRootSourceDir();
-		atomicRoot = RemoveTrailingSlash(atomicRoot);
+        String atomicRoot = tenv->GetRootSourceDir();
+        atomicRoot = RemoveTrailingSlash(atomicRoot);
 
-		path.Replace("$ATOMIC_ROOT$", atomicRoot, false);
+        path.Replace("$ATOMIC_ROOT$", atomicRoot, false);
 
-		String atomicProjectPath = projectGen_->GetAtomicProjectPath();
+        String atomicProjectPath = projectGen_->GetAtomicProjectPath();
 
-		// TODO: This is the cause of a bunch of "GetSanitizedPath" calls,
-		// It should be removed, and the few places in csproj/sln that need backslash
-		// adjusted there
-		atomicProjectPath.Replace("/", "\\");
+        // TODO: This is the cause of a bunch of "GetSanitizedPath" calls,
+        // It should be removed, and the few places in csproj/sln that need backslash
+        // adjusted there
+        atomicProjectPath.Replace("/", "\\");
 
-		if (atomicProjectPath.Length())
-		{
-			path.Replace("$ATOMIC_PROJECT_ROOT$", atomicProjectPath, false);
-		}
+        if (atomicProjectPath.Length())
+        {
+            path.Replace("$ATOMIC_PROJECT_ROOT$", atomicProjectPath, false);
+        }
 
-	}
+    }
 
-	NETCSProject::NETCSProject(Context* context, NETProjectGen* projectGen) : NETProjectBase(context, projectGen),
-		androidApplication_(false),
-		playerApplication_(false)
-	{
+    NETCSProject::NETCSProject(Context* context, NETProjectGen* projectGen) : NETProjectBase(context, projectGen),
+        androidApplication_(false),
+        playerApplication_(false)
+    {
 
-	}
+    }
 
-	NETCSProject::~NETCSProject()
-	{
+    NETCSProject::~NETCSProject()
+    {
 
-	}
+    }
 
-	bool NETCSProject::SupportsDesktop() const
-	{
-		if (!platforms_.Size())
-			return true;
+    bool NETCSProject::SupportsDesktop() const
+    {
+        if (!platforms_.Size())
+            return true;
 
-		if (platforms_.Contains("desktop") || platforms_.Contains("windows") || platforms_.Contains("macosx") || platforms_.Contains("linux"))
-			return true;
+        if (platforms_.Contains("desktop") || platforms_.Contains("windows") || platforms_.Contains("macosx") || platforms_.Contains("linux"))
+            return true;
 
-		return false;
+        return false;
 
-	}
+    }
 
-	bool NETCSProject::SupportsPlatform(const String& platform, bool explicitCheck) const
-	{
-		if (!explicitCheck && !platforms_.Size())
-			return true;
+    bool NETCSProject::SupportsPlatform(const String& platform, bool explicitCheck) const
+    {
+        if (!explicitCheck && !platforms_.Size())
+            return true;
 
-		if (platforms_.Contains(platform.ToLower()))
-			return true;
+        if (platforms_.Contains(platform.ToLower()))
+            return true;
 
-		return false;
+        return false;
 
-	}
+    }
 
-	bool NETCSProject::CreateProjectFolder(const String& path)
-	{
-		FileSystem* fileSystem = GetSubsystem<FileSystem>();
+    bool NETCSProject::CreateProjectFolder(const String& path)
+    {
+        FileSystem* fileSystem = GetSubsystem<FileSystem>();
+
+        if (fileSystem->DirExists(path))
+            return true;
 
-		if (fileSystem->DirExists(path))
-			return true;
+        fileSystem->CreateDirsRecursive(path);
 
-		fileSystem->CreateDirsRecursive(path);
+        if (!fileSystem->DirExists(path))
+        {
+            ATOMIC_LOGERRORF("Unable to create dir: %s", path.CString());
+            return false;
+        }
 
-		if (!fileSystem->DirExists(path))
-		{
-			ATOMIC_LOGERRORF("Unable to create dir: %s", path.CString());
-			return false;
-		}
+        return true;
+    }
 
-		return true;
-	}
 
+    void NETCSProject::CreateCompileItemGroup(XMLElement &projectRoot)
+    {
+        FileSystem* fs = GetSubsystem<FileSystem>();
 
-	void NETCSProject::CreateCompileItemGroup(XMLElement &projectRoot)
-	{
-		FileSystem* fs = GetSubsystem<FileSystem>();
+        XMLElement igroup = projectRoot.CreateChild("ItemGroup");
 
-		XMLElement igroup = projectRoot.CreateChild("ItemGroup");
+        // Compile AssemblyInfo.cs
 
-		// Compile AssemblyInfo.cs
+        if (!GetIsPCL() && !sharedReferences_.Size() && outputType_ != "Shared")
+            igroup.CreateChild("Compile").SetAttribute("Include", "Properties\\AssemblyInfo.cs");
 
-		if (!GetIsPCL() && !sharedReferences_.Size() && outputType_ != "Shared")
-			igroup.CreateChild("Compile").SetAttribute("Include", "Properties\\AssemblyInfo.cs");
+        for (unsigned i = 0; i < sourceFolders_.Size(); i++)
+        {
+            const String& sourceFolder = sourceFolders_[i];
 
-		for (unsigned i = 0; i < sourceFolders_.Size(); i++)
-		{
-			const String& sourceFolder = sourceFolders_[i];
+            Vector<String> result;
+            fs->ScanDir(result, sourceFolder, "*.cs", SCAN_FILES, true);
 
-			Vector<String> result;
-			fs->ScanDir(result, sourceFolder, "*.cs", SCAN_FILES, true);
+            for (unsigned j = 0; j < result.Size(); j++)
+            {
+                XMLElement compile = igroup.CreateChild("Compile");
 
-			for (unsigned j = 0; j < result.Size(); j++)
-			{
-				XMLElement compile = igroup.CreateChild("Compile");
+                String path = sourceFolder + result[j];
 
-				String path = sourceFolder + result[j];
+                String relativePath;
 
-				String relativePath;
+                if (GetRelativePath(projectPath_, GetPath(path), relativePath))
+                {
+                    path = relativePath + GetFileName(path) + GetExtension(path);
+                }
 
-				if (GetRelativePath(projectPath_, GetPath(path), relativePath))
-				{
-					path = relativePath + GetFileName(path) + GetExtension(path);
-				}
+                // IMPORTANT: / Slash direction breaks intellisense :/
+                path.Replace('/', '\\');
 
-				// IMPORTANT: / Slash direction breaks intellisense :/
-				path.Replace('/', '\\');
+                compile.SetAttribute("Include", path.CString());
 
-				compile.SetAttribute("Include", path.CString());
+                // put generated files into generated folder
+                if (sourceFolder.Contains("Generated") && sourceFolder.Contains("CSharp") && sourceFolder.Contains("Packages"))
+                {
+                    compile.CreateChild("Link").SetValue("Generated\\" + result[j]);
+                }
+                else
+                {
+                    compile.CreateChild("Link").SetValue(result[j]);
+                }
 
-				// put generated files into generated folder
-				if (sourceFolder.Contains("Generated") && sourceFolder.Contains("CSharp") && sourceFolder.Contains("Packages"))
-				{
-					compile.CreateChild("Link").SetValue("Generated\\" + result[j]);
-				}
-				else
-				{
-					compile.CreateChild("Link").SetValue(result[j]);
-				}
+            }
 
-			}
+        }
 
-		}
+    }
 
-	}
+    void NETProjectBase::CopyXMLElementRecursive(XMLElement source, XMLElement dest)
+    {
+        Vector<String> attrNames = source.GetAttributeNames();
 
-	void NETProjectBase::CopyXMLElementRecursive(XMLElement source, XMLElement dest)
-	{
-		Vector<String> attrNames = source.GetAttributeNames();
+        for (unsigned i = 0; i < attrNames.Size(); i++)
+        {
+            String value = source.GetAttribute(attrNames[i]);
+            dest.SetAttribute(attrNames[i], value);
+        }
 
-		for (unsigned i = 0; i < attrNames.Size(); i++)
-		{
-			String value = source.GetAttribute(attrNames[i]);
-			dest.SetAttribute(attrNames[i], value);
-		}
+        dest.SetValue(source.GetValue());
 
-		dest.SetValue(source.GetValue());
+        XMLElement child = source.GetChild();
 
-		XMLElement child = source.GetChild();
+        while (child.NotNull() && child.GetName().Length())
+        {
+            XMLElement childDest = dest.CreateChild(child.GetName());
+            CopyXMLElementRecursive(child, childDest);
+            child = child.GetNext();
+        }
+    }
 
-		while (child.NotNull() && child.GetName().Length())
-		{
-			XMLElement childDest = dest.CreateChild(child.GetName());
-			CopyXMLElementRecursive(child, childDest);
-			child = child.GetNext();
-		}
-	}
+    void NETCSProject::CreateReferencesItemGroup(XMLElement &projectRoot)
+    {
+        ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
 
-	void NETCSProject::CreateReferencesItemGroup(XMLElement &projectRoot)
-	{
-		ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+        XMLElement xref;
+        XMLElement igroup = projectRoot.CreateChild("ItemGroup");
 
-		XMLElement xref;
-		XMLElement igroup = projectRoot.CreateChild("ItemGroup");
+        for (unsigned i = 0; i < references_.Size(); i++)
+        {
+            String ref = references_[i];
 
-		for (unsigned i = 0; i < references_.Size(); i++)
-		{
-			String ref = references_[i];
+            // project reference
+            if (projectGen_->GetCSProjectByName(ref))
+                continue;
 
-			// project reference
-			if (projectGen_->GetCSProjectByName(ref))
-				continue;
+            String platform;
 
-			String platform;
+            if (projectGen_->GetAtomicProjectPath().Length() && ref.StartsWith("AtomicNET"))
+            {
+                if (GetIsPCL())
+                {
+                    ref = "AtomicNET";
+                    platform = "Portable";
+                }
+                else if (SupportsDesktop())
+                {
+                    ref = "AtomicNET";
+                    platform = "Desktop";
+                }
+                else if (SupportsPlatform("android"))
+                {
+                    if (ref != "AtomicNET.Android.SDL")
+                        ref = "AtomicNET";
 
-			if (projectGen_->GetAtomicProjectPath().Length() && ref.StartsWith("AtomicNET"))
-			{
-				if (GetIsPCL())
-				{
-					ref = "AtomicNET";
-					platform = "Portable";
-				}
-				else if (SupportsDesktop())
-				{
-					ref = "AtomicNET";
-					platform = "Desktop";
-				}
-				else if (SupportsPlatform("android"))
-				{
-					if (ref != "AtomicNET.Android.SDL")
-						ref = "AtomicNET";
+                    platform = "Android";
+                }
+                else if (SupportsPlatform("ios"))
+                {
+                    ref = "AtomicNET";
+                    platform = "iOS";
+                }
 
-					platform = "Android";
-				}
 
-				if (platform.Length())
-				{
-					String atomicNETAssembly = tenv->GetAtomicNETCoreAssemblyDir() + ToString("%s/%s.dll", platform.CString(), ref.CString());
-					xref = igroup.CreateChild("Reference");
-					xref.SetAttribute("Include", atomicNETAssembly);
-				}
+                if (platform.Length())
+                {
+                    String atomicNETAssembly = tenv->GetAtomicNETCoreAssemblyDir() + ToString("%s/%s.dll", platform.CString(), ref.CString());
+                    xref = igroup.CreateChild("Reference");
+                    xref.SetAttribute("Include", atomicNETAssembly);
+                }
 
-				continue;
+                continue;
 
-			}
+            }
 
-			// NuGet project
-			if (ref.StartsWith("<"))
-			{
-				XMLFile xmlFile(context_);
+            // NuGet project
+            if (ref.StartsWith("<"))
+            {
+                XMLFile xmlFile(context_);
 
-				if (!xmlFile.FromString(ref))
-				{
-					ATOMIC_LOGERROR("NETCSProject::CreateReferencesItemGroup - Unable to parse reference XML");
-				}
+                if (!xmlFile.FromString(ref))
+                {
+                    ATOMIC_LOGERROR("NETCSProject::CreateReferencesItemGroup - Unable to parse reference XML");
+                }
 
 
-				xref = igroup.CreateChild("Reference");
-				CopyXMLElementRecursive(xmlFile.GetRoot(), xref);
-				continue;
-			}
+                xref = igroup.CreateChild("Reference");
+                CopyXMLElementRecursive(xmlFile.GetRoot(), xref);
+                continue;
+            }
 
-			xref = igroup.CreateChild("Reference");
-			xref.SetAttribute("Include", ref);
+            xref = igroup.CreateChild("Reference");
+            xref.SetAttribute("Include", ref);
 
-		}
+        }
 
-		const String atomicProjectPath = projectGen_->GetAtomicProjectPath();
+        const String atomicProjectPath = projectGen_->GetAtomicProjectPath();
 
-		if (atomicProjectPath.Length())
-		{
-			String resourceDir = AddTrailingSlash(atomicProjectPath) + "Resources/";
+        if (atomicProjectPath.Length())
+        {
+            String resourceDir = AddTrailingSlash(atomicProjectPath) + "Resources/";
 
-			Vector<String> result;
-			GetSubsystem<FileSystem>()->ScanDir(result, resourceDir , "*.dll", SCAN_FILES, true);
+            Vector<String> result;
+            GetSubsystem<FileSystem>()->ScanDir(result, resourceDir , "*.dll", SCAN_FILES, true);
 
-			for (unsigned j = 0; j < result.Size(); j++)
-			{
-				String path = resourceDir + result[j];
+            for (unsigned j = 0; j < result.Size(); j++)
+            {
+                String path = resourceDir + result[j];
 
-				String relativePath;
+                String relativePath;
 
-				if (GetRelativePath(projectPath_, GetPath(path), relativePath))
-				{
-					if (projectGen_->GetCSProjectByName(GetFileName(path)))
-						continue;
+                if (GetRelativePath(projectPath_, GetPath(path), relativePath))
+                {
+                    if (projectGen_->GetCSProjectByName(GetFileName(path)))
+                        continue;
 
-					path = relativePath + GetFileName(path) + GetExtension(path);
-				}
+                    path = relativePath + GetFileName(path) + GetExtension(path);
+                }
 
-				xref = igroup.CreateChild("Reference");
-				xref.SetAttribute("Include", path);
-			}
+                xref = igroup.CreateChild("Reference");
+                xref.SetAttribute("Include", path);
+            }
 
-		}
+        }
 
-	}
+    }
 
-	void NETCSProject::CreateProjectReferencesItemGroup(XMLElement &projectRoot)
-	{
+    void NETCSProject::CreateProjectReferencesItemGroup(XMLElement &projectRoot)
+    {
 
-		XMLElement igroup = projectRoot.CreateChild("ItemGroup");
+        XMLElement igroup = projectRoot.CreateChild("ItemGroup");
 
-		for (unsigned i = 0; i < references_.Size(); i++)
-		{
-			const String& ref = references_[i];
-			NETCSProject* project = projectGen_->GetCSProjectByName(ref);
+        for (unsigned i = 0; i < references_.Size(); i++)
+        {
+            const String& ref = references_[i];
+            NETCSProject* project = projectGen_->GetCSProjectByName(ref);
 
-			if (!project)
-				continue;
+            if (!project)
+                continue;
 
 
-			XMLElement projectRef = igroup.CreateChild("ProjectReference");
-			projectRef.SetAttribute("Include", ToString("..\\%s\\%s.csproj", ref.CString(), ref.CString()));
+            XMLElement projectRef = igroup.CreateChild("ProjectReference");
+            projectRef.SetAttribute("Include", ToString("..\\%s\\%s.csproj", ref.CString(), ref.CString()));
 
-			XMLElement xproject = projectRef.CreateChild("Project");
-			xproject.SetValue(ToString("{%s}", project->GetProjectGUID().ToLower().CString()));
+            XMLElement xproject = projectRef.CreateChild("Project");
+            xproject.SetValue(ToString("{%s}", project->GetProjectGUID().ToLower().CString()));
 
-			XMLElement xname = projectRef.CreateChild("Name");
-			xname.SetValue(project->GetName());
-		}
-	}
+            XMLElement xname = projectRef.CreateChild("Name");
+            xname.SetValue(project->GetName());
+        }
+    }
 
 
-	void NETCSProject::CreatePackagesItemGroup(XMLElement &projectRoot)
-	{
-		if (!packages_.Size())
-			return;
+    void NETCSProject::CreatePackagesItemGroup(XMLElement &projectRoot)
+    {
+        if (!packages_.Size())
+            return;
 
-		XMLElement xref;
-		XMLElement igroup = projectRoot.CreateChild("ItemGroup");
-		xref = igroup.CreateChild("None");
-		xref.SetAttribute("Include", "packages.config");
+        XMLElement xref;
+        XMLElement igroup = projectRoot.CreateChild("ItemGroup");
+        xref = igroup.CreateChild("None");
+        xref.SetAttribute("Include", "packages.config");
 
-		XMLFile packageConfig(context_);
+        XMLFile packageConfig(context_);
 
-		XMLElement packageRoot = packageConfig.CreateRoot("packages");
+        XMLElement packageRoot = packageConfig.CreateRoot("packages");
 
-		for (unsigned i = 0; i < packages_.Size(); i++)
-		{
-			XMLFile xmlFile(context_);
-			if (!xmlFile.FromString(packages_[i]))
-			{
-				ATOMIC_LOGERROR("NETCSProject::CreatePackagesItemGroup - Unable to parse package xml");
-			}
+        for (unsigned i = 0; i < packages_.Size(); i++)
+        {
+            XMLFile xmlFile(context_);
+            if (!xmlFile.FromString(packages_[i]))
+            {
+                ATOMIC_LOGERROR("NETCSProject::CreatePackagesItemGroup - Unable to parse package xml");
+            }
 
-			xref = packageRoot.CreateChild("package");
+            xref = packageRoot.CreateChild("package");
 
-			CopyXMLElementRecursive(xmlFile.GetRoot(), xref);
-		}
+            CopyXMLElementRecursive(xmlFile.GetRoot(), xref);
+        }
 
         SharedPtr<File> output(new File(context_, GetSanitizedPath(projectPath_ + "packages.config"), FILE_WRITE));
-		String source = packageConfig.ToString();
-		output->Write(source.CString(), source.Length());
+        String source = packageConfig.ToString();
+        output->Write(source.CString(), source.Length());
+
+    }
 
-	}
+    void NETCSProject::GetAssemblySearchPaths(String& paths)
+    {
+        paths.Clear();
 
-	void NETCSProject::GetAssemblySearchPaths(String& paths)
-	{
-		paths.Clear();
+        ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
 
-		ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+        Vector<String> searchPaths;
 
-		Vector<String> searchPaths;
+        if (assemblySearchPaths_.Length())
+            searchPaths.Push(assemblySearchPaths_);
 
-		if (assemblySearchPaths_.Length())
-			searchPaths.Push(assemblySearchPaths_);
+        paths.Join(searchPaths, ";");
+    }
 
-		paths.Join(searchPaths, ";");
-	}
+    void NETCSProject::ProcessDefineConstants(StringVector& constants)
+    {
+        const Vector<String>& globalConstants = projectGen_->GetGlobalDefineConstants();
+        constants += globalConstants;
 
-	void NETCSProject::CreateReleasePropertyGroup(XMLElement &projectRoot)
-	{
-		XMLElement pgroup = projectRoot.CreateChild("PropertyGroup");
-		pgroup.SetAttribute("Condition", " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ");
+        if (constants.Contains("ATOMIC_IOS") || constants.Contains("ATOMIC_ANDROID"))
+            constants.Push("ATOMIC_MOBILE");
+    }
 
-		pgroup.CreateChild("Optimize").SetValue("true");
+    void NETCSProject::CreateReleasePropertyGroup(XMLElement &projectRoot)
+    {
+        XMLElement pgroup = projectRoot.CreateChild("PropertyGroup");
 
-		String outputPath = assemblyOutputPath_;
-		outputPath.Replace("$ATOMIC_CONFIG$", "Release");
+        if (playerApplication_ && SupportsPlatform("ios"))
+            pgroup.SetAttribute("Condition", " '$(Configuration)|$(Platform)' == 'Release|iPhone' ");
+        else
+            pgroup.SetAttribute("Condition", " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ");
 
-		pgroup.CreateChild("OutputPath").SetValue(outputPath);
+        pgroup.CreateChild("Optimize").SetValue("true");
 
-		Vector<String> constants;
-		constants.Push("TRACE");
+        String outputPath = assemblyOutputPath_;
+        outputPath.Replace("$ATOMIC_CONFIG$", "Release");
 
-		constants += defineConstants_;
+        pgroup.CreateChild("OutputPath").SetValue(outputPath);
 
-		const Vector<String>& globalConstants = projectGen_->GetGlobalDefineConstants();
-		constants += globalConstants;
+        Vector<String> constants;
+        constants.Push("TRACE");
 
-		pgroup.CreateChild("DefineConstants").SetValue(String::Joined(constants, ";").CString());
-		pgroup.CreateChild("ErrorReport").SetValue("prompt");
-		pgroup.CreateChild("WarningLevel").SetValue("4");
-		pgroup.CreateChild("ConsolePause").SetValue("false");
-		pgroup.CreateChild("AllowUnsafeBlocks").SetValue("true");
+        constants += defineConstants_;
 
-		if (SupportsDesktop())
-		{
-			pgroup.CreateChild("DebugType").SetValue(GetIsPCL() ? "pdbonly": "full");
-			if (!GetIsPCL())
-				pgroup.CreateChild("PlatformTarget").SetValue("x64");
+        ProcessDefineConstants(constants);
+
+        pgroup.CreateChild("DefineConstants").SetValue(String::Joined(constants, ";").CString());
+        pgroup.CreateChild("ErrorReport").SetValue("prompt");
+        pgroup.CreateChild("WarningLevel").SetValue("4");
+        pgroup.CreateChild("ConsolePause").SetValue("false");
+        pgroup.CreateChild("AllowUnsafeBlocks").SetValue("true");
+
+        if (SupportsDesktop())
+        {
+            pgroup.CreateChild("DebugType").SetValue(GetIsPCL() ? "pdbonly": "full");
+            if (!GetIsPCL())
+                pgroup.CreateChild("PlatformTarget").SetValue("x64");
 
 #ifndef ATOMIC_PLATFORM_WINDOWS
 
@@ -426,59 +444,73 @@ namespace ToolCore
             pgroup.CreateChild("Commandlineparameters").SetValue(startArguments);
 #endif
 
-		}
-		else
-		{
-			pgroup.CreateChild("DebugType").SetValue("pdbonly");
+        }
+        else
+        {
+            if (SupportsPlatform("android"))
+            {
+                pgroup.CreateChild("DebugType").SetValue("pdbonly");
 
-			if (SupportsPlatform("android"))
-			{
-				if (outputType_.ToLower() != "library")
-				{
-					pgroup.CreateChild("AndroidUseSharedRuntime").SetValue("False");
-					pgroup.CreateChild("AndroidLinkMode").SetValue("SdkOnly");
-				}
-			}
-		}
+                if (outputType_.ToLower() != "library")
+                {
+                    pgroup.CreateChild("AndroidUseSharedRuntime").SetValue("False");
+                    pgroup.CreateChild("AndroidLinkMode").SetValue("SdkOnly");
+                }
+            }
+            else if (playerApplication_ && SupportsPlatform("ios"))
+            {
+                pgroup.CreateChild("DebugType").SetValue("none");
 
-	}
+                pgroup.CreateChild("MtouchArch").SetValue("ARMv7, ARM64");
+                pgroup.CreateChild("CodesignEntitlements").SetValue(GetSanitizedPath(codesignEntitlements_));
+                pgroup.CreateChild("CodesignKey").SetValue("iPhone Developer");
+                pgroup.CreateChild("MtouchDebug").SetValue("true");
+                pgroup.CreateChild("MtouchOptimizePNGs").SetValue("False");
+            }
 
-	void NETCSProject::CreateDebugPropertyGroup(XMLElement &projectRoot)
-	{
-		XMLElement pgroup = projectRoot.CreateChild("PropertyGroup");
-		pgroup.SetAttribute("Condition", " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ");
+        }
 
-		pgroup.CreateChild("Optimize").SetValue("false");
+    }
 
-		String outputPath = assemblyOutputPath_;
-		outputPath.Replace("$ATOMIC_CONFIG$", "Debug");
+    void NETCSProject::CreateDebugPropertyGroup(XMLElement &projectRoot)
+    {
+        XMLElement pgroup = projectRoot.CreateChild("PropertyGroup");
 
-		pgroup.CreateChild("OutputPath").SetValue(outputPath);
+        if (playerApplication_ && SupportsPlatform("ios"))
+            pgroup.SetAttribute("Condition", " '$(Configuration)|$(Platform)' == 'Debug|iPhone' ");
+        else
+            pgroup.SetAttribute("Condition", " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ");
 
-		Vector<String> constants;
-		constants.Push("DEBUG");
-		constants.Push("TRACE");
 
-		constants += defineConstants_;
+        pgroup.CreateChild("Optimize").SetValue("false");
 
-		const Vector<String>& globalConstants = projectGen_->GetGlobalDefineConstants();
-		constants += globalConstants;
+        String outputPath = assemblyOutputPath_;
+        outputPath.Replace("$ATOMIC_CONFIG$", "Debug");
 
-		pgroup.CreateChild("DefineConstants").SetValue(String::Joined(constants, ";").CString());
+        pgroup.CreateChild("OutputPath").SetValue(outputPath);
 
-		pgroup.CreateChild("ErrorReport").SetValue("prompt");
-		pgroup.CreateChild("WarningLevel").SetValue("4");
-		pgroup.CreateChild("ConsolePause").SetValue("false");
-		pgroup.CreateChild("AllowUnsafeBlocks").SetValue("true");
+        Vector<String> constants;
+        constants.Push("DEBUG");
+        constants.Push("TRACE");
+
+        constants += defineConstants_;
+        ProcessDefineConstants(constants);
+
+        pgroup.CreateChild("DefineConstants").SetValue(String::Joined(constants, ";").CString());
+
+        pgroup.CreateChild("ErrorReport").SetValue("prompt");
+        pgroup.CreateChild("WarningLevel").SetValue("4");
+        pgroup.CreateChild("ConsolePause").SetValue("false");
+        pgroup.CreateChild("AllowUnsafeBlocks").SetValue("true");
 
         pgroup.CreateChild("DebugSymbols").SetValue("true");
 
-		if (SupportsDesktop())
-		{
+        if (SupportsDesktop())
+        {
             pgroup.CreateChild("DebugType").SetValue(GetIsPCL() ? "pdbonly": "full");
 
-			if (!GetIsPCL())
-				pgroup.CreateChild("PlatformTarget").SetValue("x64");
+            if (!GetIsPCL())
+                pgroup.CreateChild("PlatformTarget").SetValue("x64");
 
 #ifndef ATOMIC_PLATFORM_WINDOWS
 
@@ -500,1200 +532,1302 @@ namespace ToolCore
             pgroup.CreateChild("Commandlineparameters").SetValue(startArguments);
 #endif
 
-		}
-		else
-		{
+        }
+        else
+        {
             pgroup.CreateChild("DebugType").SetValue(GetIsPCL() ? "pdbonly": "full");
 
-			if (androidApplication_)
-			{
-				pgroup.CreateChild("AndroidUseSharedRuntime").SetValue("False");
-				pgroup.CreateChild("AndroidLinkMode").SetValue("None");
-				pgroup.CreateChild("EmbedAssembliesIntoApk").SetValue("True");
-				pgroup.CreateChild("BundleAssemblies").SetValue("False");
-				pgroup.CreateChild("AndroidCreatePackagePerAbi").SetValue("False");
-				pgroup.CreateChild("Debugger").SetValue("Xamarin");
-				pgroup.CreateChild("AndroidEnableMultiDex").SetValue("False");
-				pgroup.CreateChild("AndroidSupportedAbis").SetValue("armeabi-v7a");
-			}
-		}
-
-
-	}
-
-	void NETCSProject::CreateApplicationItems(XMLElement &projectRoot)
-	{
-		ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
-
-		XMLElement itemGroup = projectRoot.CreateChild("ItemGroup");
-
-		if (SupportsDesktop())
-		{
-			// AtomicNETNative
-
-			XMLElement atomicNETNativeDLL = itemGroup.CreateChild("None");
+            if (androidApplication_)
+            {
+                pgroup.CreateChild("AndroidUseSharedRuntime").SetValue("False");
+                pgroup.CreateChild("AndroidLinkMode").SetValue("None");
+                pgroup.CreateChild("EmbedAssembliesIntoApk").SetValue("True");
+                pgroup.CreateChild("BundleAssemblies").SetValue("False");
+                pgroup.CreateChild("AndroidCreatePackagePerAbi").SetValue("False");
+                pgroup.CreateChild("Debugger").SetValue("Xamarin");
+                pgroup.CreateChild("AndroidEnableMultiDex").SetValue("False");
+                pgroup.CreateChild("AndroidSupportedAbis").SetValue("armeabi-v7a");
+            }
+            else if (playerApplication_ && SupportsPlatform("ios"))
+            {
+                pgroup.CreateChild("MtouchArch").SetValue("ARMv7, ARM64");
+                pgroup.CreateChild("CodesignEntitlements").SetValue(GetSanitizedPath(codesignEntitlements_));
+                pgroup.CreateChild("CodesignKey").SetValue("iPhone Developer");
+                pgroup.CreateChild("MtouchDebug").SetValue("true");
+                pgroup.CreateChild("MtouchFastDev").SetValue("true");
+                pgroup.CreateChild("IpaPackageName").SetValue("");
+                pgroup.CreateChild("OptimizePNGs").SetValue("false");
+                pgroup.CreateChild("MtouchOptimizePNGs").SetValue("False");
+            }
+        }
+
+
+    }
+
+    void NETCSProject::CreateApplicationItems(XMLElement &projectRoot)
+    {
+        ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+
+        XMLElement itemGroup = projectRoot.CreateChild("ItemGroup");
+
+        if (SupportsDesktop())
+        {
+            // AtomicNETNative
+
+            XMLElement atomicNETNativeDLL = itemGroup.CreateChild("None");
 
 #ifdef ATOMIC_DEBUG
-			String config = "Debug";
+            String config = "Debug";
 #else
-			String config = "Release";
+            String config = "Release";
 #endif
 
 #ifdef ATOMIC_PLATFORM_WINDOWS
-			String platform = "Windows";
-			String filename = "AtomicNETNative.dll";
+            String platform = "Windows";
+            String filename = "AtomicNETNative.dll";
 #elif defined(ATOMIC_PLATFORM_OSX)
-			String platform = "Mac";
+            String platform = "Mac";
             String filename = "libAtomicNETNative.dylib";
 #elif defined(ATOMIC_PLATFORM_LINUX)
-			String platform = "Linux";
-			String filename = "libAtomicNETNative.so";
+            String platform = "Linux";
+            String filename = "libAtomicNETNative.so";
 #endif
 
 #ifdef ATOMIC_DEV_BUILD
 
-			String nativePath = AddTrailingSlash(tenv->GetAtomicNETRootDir()) + config + "/Native/" + platform + "/" + filename;
+            String nativePath = AddTrailingSlash(tenv->GetAtomicNETRootDir()) + config + "/Native/" + platform + "/" + filename;
 #else
-			String nativePath = AddTrailingSlash(tenv->GetAtomicNETRootDir()) + config + "/Native/" + platform + "/" + filename;
+            String nativePath = AddTrailingSlash(tenv->GetAtomicNETRootDir()) + config + "/Native/" + platform + "/" + filename;
 #endif
-			atomicNETNativeDLL.SetAttribute("Include", nativePath);
-			atomicNETNativeDLL.CreateChild("Link").SetValue(filename);
-			atomicNETNativeDLL.CreateChild("CopyToOutputDirectory").SetValue("PreserveNewest");
+            atomicNETNativeDLL.SetAttribute("Include", nativePath);
+            atomicNETNativeDLL.CreateChild("Link").SetValue(filename);
+            atomicNETNativeDLL.CreateChild("CopyToOutputDirectory").SetValue("PreserveNewest");
 
 #ifdef ATOMIC_PLATFORM_WINDOWS
-			XMLElement d3dCompilerDLL = itemGroup.CreateChild("None");
-			String d3dCompilerPath = AddTrailingSlash(tenv->GetAtomicNETRootDir()) + config + "/Native/" + platform + "/D3DCompiler_47.dll";
-			d3dCompilerDLL.SetAttribute("Include", d3dCompilerPath);
-			d3dCompilerDLL.CreateChild("Link").SetValue("D3DCompiler_47.dll");
-			d3dCompilerDLL.CreateChild("CopyToOutputDirectory").SetValue("PreserveNewest");
+            XMLElement d3dCompilerDLL = itemGroup.CreateChild("None");
+            String d3dCompilerPath = AddTrailingSlash(tenv->GetAtomicNETRootDir()) + config + "/Native/" + platform + "/D3DCompiler_47.dll";
+            d3dCompilerDLL.SetAttribute("Include", d3dCompilerPath);
+            d3dCompilerDLL.CreateChild("Link").SetValue("D3DCompiler_47.dll");
+            d3dCompilerDLL.CreateChild("CopyToOutputDirectory").SetValue("PreserveNewest");
 #endif
-		}
-		else
-		{
-			const String& projectPath = projectGen_->GetAtomicProjectPath();
-			if (!playerApplication_ || !projectPath.Length())
-				return;
-
-			XMLElement androidAsset = itemGroup.CreateChild("AndroidAsset");
-			androidAsset.SetAttribute("Include", projectPath + "AtomicNET/Resources/AtomicResources.pak");
-			androidAsset.CreateChild("Link").SetValue("Assets\\AtomicResources.pak");
-		}
-
-	}
-
-	void NETCSProject::CreateAndroidItems(XMLElement &projectRoot)
-	{
-
-		if (!libraryProjectZips_.Size())
-		{
-		}
-
-		if (libraryProjectZips_.Size())
-		{
-			XMLElement libraryGroup = projectRoot.CreateChild("ItemGroup");
-
-			for (unsigned i = 0; i < libraryProjectZips_.Size(); i++)
-			{
-				libraryGroup.CreateChild("LibraryProjectZip").SetAttribute("Include", libraryProjectZips_[i].CString());
-			}
-		}
-
-		if (transformFiles_.Size())
-		{
-			XMLElement transformGroup = projectRoot.CreateChild("ItemGroup");
-
-			for (unsigned i = 0; i < transformFiles_.Size(); i++)
-			{
-				transformGroup.CreateChild("TransformFile").SetAttribute("Include", transformFiles_[i].CString());
-			}
-		}
-
-		if (!importProjects_.Size())
-		{
-			projectRoot.CreateChild("Import").SetAttribute("Project", "$(MSBuildExtensionsPath)\\Xamarin\\Android\\Xamarin.Android.CSharp.targets");
-		}
-
-		if (androidApplication_)
-		{
-			// TODO: other abi
-			ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+        }
+        else
+        {
+            const String& projectPath = projectGen_->GetAtomicProjectPath();            
+            if (!playerApplication_ || !projectPath.Length())
+                return;
+
+            if (androidApplication_)
+            {
+                XMLElement androidAsset = itemGroup.CreateChild("AndroidAsset");
+                androidAsset.SetAttribute("Include", projectPath + "AtomicNET/Resources/AtomicResources.pak");
+                androidAsset.CreateChild("Link").SetValue("Assets\\AtomicResources.pak");
+            }
+            else
+            {
+                XMLElement bundleResource = itemGroup.CreateChild("BundleResource");
+                bundleResource.SetAttribute("Include", projectPath + "AtomicNET/Resources/AtomicResources.pak");
+                bundleResource.CreateChild("Link").SetValue("Resources\\AtomicResources.pak");
+                bundleResource.CreateChild("CopyToOutputDirectory").SetValue("PreserveNewest");
+            }
+        }
+
+    }
+
+    void NETCSProject::CreateIOSItems(XMLElement &projectRoot)
+    {
+        XMLElement iosGroup = projectRoot.CreateChild("ItemGroup");
+
+        if (objcBindingApiDefinition_.Length())
+        {
+            iosGroup.CreateChild("ObjcBindingApiDefinition").SetAttribute("Include", GetSanitizedPath(objcBindingApiDefinition_));
+        }
+
+        if (name_ == "AtomicNET.iOS")
+        {
+            ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
 
 #ifdef ATOMIC_DEBUG
-			String config = "Debug";
+            String config = "Debug";
 #else
-			String config = "Release";
+            String config = "Release";
 #endif
 
-			// TODO: more than armeabi-v7a (which this is)
-			String nativePath = AddTrailingSlash(tenv->GetAtomicNETRootDir()) + config + "/Native/Android/libAtomicNETNative.so";
-
-			XMLElement nativeLibrary =  projectRoot.CreateChild("ItemGroup").CreateChild("AndroidNativeLibrary");
-			nativeLibrary.SetAttribute("Include", nativePath);
-
-			nativeLibrary.CreateChild("Link").SetValue("Libs\\armeabi-v7a\\libAtomicNETNative.so");
-
-			XMLElement resourceGroup = projectRoot.CreateChild("ItemGroup");
-
-			String relativePath;
-
-			if (GetRelativeProjectPath("$ATOMIC_PROJECT_ROOT$/Project/AtomicNET/Platforms/Android/Resources/values/Strings.xml", projectPath_, relativePath))
-			{
-				relativePath.Replace("/", "\\");
-
-				XMLElement strings = resourceGroup.CreateChild("AndroidResource");
-				strings.SetAttribute("Include", relativePath);
-				// Link has to exist for manifest to find resource!
-				strings.CreateChild("Link").SetValue("Resources\\values\\Strings.xml");
-			}
-			else
-			{
-				ATOMIC_LOGERROR("Unabled to get relative path for Strings.xml");
-			}
+            String nativePath = AddTrailingSlash(tenv->GetAtomicNETRootDir()) + config + "/Native/iOS/AtomicNETNative.framework";
+            iosGroup.CreateChild("ObjcBindingNativeFramework").SetAttribute("Include", GetSanitizedPath(nativePath));
+
+            // framework copy
+            XMLElement none = iosGroup.CreateChild("None");
+            none.SetAttribute("Include", nativePath + ".zip");
+            none.CreateChild("Link").SetValue("AtomicNETNative.framework.zip");
+            none.CreateChild("CopyToOutputDirectory").SetValue("Always");
+
+        }
+        else if (playerApplication_)
+        {
+            XMLElement plist = iosGroup.CreateChild("None");
+            plist.SetAttribute("Include", GetSanitizedPath(infoPList_));
+            plist.CreateChild("Link").SetValue("Info.plist");
+
+            XMLElement entitlements = iosGroup.CreateChild("Content");
+            entitlements.SetAttribute("Include", GetSanitizedPath(codesignEntitlements_));
+            entitlements.CreateChild("Link").SetValue("Entitlements.plist");
+        }
+
+    }
+
+    void NETCSProject::CreateAndroidItems(XMLElement &projectRoot)
+    {
+
+        if (!libraryProjectZips_.Size())
+        {
+        }
+
+        if (libraryProjectZips_.Size())
+        {
+            XMLElement libraryGroup = projectRoot.CreateChild("ItemGroup");
+
+            for (unsigned i = 0; i < libraryProjectZips_.Size(); i++)
+            {
+                libraryGroup.CreateChild("LibraryProjectZip").SetAttribute("Include", libraryProjectZips_[i].CString());
+            }
+        }
+
+        if (transformFiles_.Size())
+        {
+            XMLElement transformGroup = projectRoot.CreateChild("ItemGroup");
+
+            for (unsigned i = 0; i < transformFiles_.Size(); i++)
+            {
+                transformGroup.CreateChild("TransformFile").SetAttribute("Include", transformFiles_[i].CString());
+            }
+        }
+
+        if (!importProjects_.Size())
+        {
+            projectRoot.CreateChild("Import").SetAttribute("Project", "$(MSBuildExtensionsPath)\\Xamarin\\Android\\Xamarin.Android.CSharp.targets");
+        }
+
+        if (androidApplication_)
+        {
+            // TODO: other abi
+            ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
 
-			if (GetRelativeProjectPath("$ATOMIC_PROJECT_ROOT$/Project/AtomicNET/Platforms/Android/Resources/drawable/icon.png", projectPath_, relativePath))
-			{
-				relativePath.Replace("/", "\\");
-				XMLElement icon = resourceGroup.CreateChild("AndroidResource");
-				icon.SetAttribute("Include", relativePath);
-				// Link has to exist for manifest to find resource!
-				icon.CreateChild("Link").SetValue("Resources\\drawable\\icon.png");
-			}
-			else
-			{
-				ATOMIC_LOGERROR("Unabled to get relative path for Icon.png");
-			}
-
-		}
+#ifdef ATOMIC_DEBUG
+            String config = "Debug";
+#else
+            String config = "Release";
+#endif
 
-	}
+            // TODO: more than armeabi-v7a (which this is)
+            String nativePath = AddTrailingSlash(tenv->GetAtomicNETRootDir()) + config + "/Native/Android/libAtomicNETNative.so";
 
-	void NETCSProject::CreateAssemblyInfo()
-	{
+            XMLElement nativeLibrary =  projectRoot.CreateChild("ItemGroup").CreateChild("AndroidNativeLibrary");
+            nativeLibrary.SetAttribute("Include", nativePath);
 
-		String info = "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n\n";
-		info += ToString("[assembly:AssemblyTitle(\"%s\")]\n", name_.CString());
-		info += "[assembly:AssemblyDescription(\"\")]\n";
-		info += "[assembly:AssemblyConfiguration(\"\")]\n";
-		info += "[assembly:AssemblyCompany(\"\")]\n";
-		info += ToString("[assembly:AssemblyProduct(\"%s\")]\n", name_.CString());
+            nativeLibrary.CreateChild("Link").SetValue("Libs\\armeabi-v7a\\libAtomicNETNative.so");
 
-		info += "\n\n\n";
+            XMLElement resourceGroup = projectRoot.CreateChild("ItemGroup");
 
-		info += "[assembly:ComVisible(false)]\n";
+            String relativePath;
 
-		info += "\n\n";
+            if (GetRelativeProjectPath("$ATOMIC_PROJECT_ROOT$/Project/AtomicNET/Platforms/Android/Resources/values/Strings.xml", projectPath_, relativePath))
+            {
+                relativePath.Replace("/", "\\");
 
-		info += ToString("[assembly:Guid(\"%s\")]\n", projectGuid_.CString());
+                XMLElement strings = resourceGroup.CreateChild("AndroidResource");
+                strings.SetAttribute("Include", relativePath);
+                // Link has to exist for manifest to find resource!
+                strings.CreateChild("Link").SetValue("Resources\\values\\Strings.xml");
+            }
+            else
+            {
+                ATOMIC_LOGERROR("Unabled to get relative path for Strings.xml");
+            }
 
-		info += "\n\n";
+            if (GetRelativeProjectPath("$ATOMIC_PROJECT_ROOT$/Project/AtomicNET/Platforms/Android/Resources/drawable/icon.png", projectPath_, relativePath))
+            {
+                relativePath.Replace("/", "\\");
+                XMLElement icon = resourceGroup.CreateChild("AndroidResource");
+                icon.SetAttribute("Include", relativePath);
+                // Link has to exist for manifest to find resource!
+                icon.CreateChild("Link").SetValue("Resources\\drawable\\icon.png");
+            }
+            else
+            {
+                ATOMIC_LOGERROR("Unabled to get relative path for Icon.png");
+            }
 
-		info += "[assembly:AssemblyVersion(\"1.0.0.0\")]\n";
-		info += "[assembly:AssemblyFileVersion(\"1.0.0.0\")]\n";
+        }
 
-        SharedPtr<File> output(new File(context_, GetSanitizedPath(projectPath_ + "Properties/AssemblyInfo.cs"), FILE_WRITE));
-		output->Write(info.CString(), info.Length());
+    }
 
-	}
+    void NETCSProject::CreateAssemblyInfo()
+    {
 
-	bool NETCSProject::GetRelativeProjectPath(const String& fromPath, const String& toPath, String& output)
-	{
-		String path = fromPath;
-		ReplacePathStrings(path);
-		path = GetSanitizedPath(path);
+        String info = "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n\n";
+        info += ToString("[assembly:AssemblyTitle(\"%s\")]\n", name_.CString());
+        info += "[assembly:AssemblyDescription(\"\")]\n";
+        info += "[assembly:AssemblyConfiguration(\"\")]\n";
+        info += "[assembly:AssemblyCompany(\"\")]\n";
+        info += ToString("[assembly:AssemblyProduct(\"%s\")]\n", name_.CString());
 
-		String relativePath;
+        info += "\n\n\n";
 
-		if (GetRelativePath(projectPath_, GetPath(path), relativePath))
-		{
-			path = relativePath + GetFileName(path) + GetExtension(path);
+        info += "[assembly:ComVisible(false)]\n";
 
-			output = path;
+        info += "\n\n";
 
-			return true;
-		}
+        info += ToString("[assembly:Guid(\"%s\")]\n", projectGuid_.CString());
 
-		output = fromPath;
+        info += "\n\n";
 
-		return false;
+        info += "[assembly:AssemblyVersion(\"1.0.0.0\")]\n";
+        info += "[assembly:AssemblyFileVersion(\"1.0.0.0\")]\n";
 
-	}
+        SharedPtr<File> output(new File(context_, GetSanitizedPath(projectPath_ + "Properties/AssemblyInfo.cs"), FILE_WRITE));
+        output->Write(info.CString(), info.Length());
 
-	void NETCSProject::CreateMainPropertyGroup(XMLElement& projectRoot)
-	{
-		XMLElement pgroup = projectRoot.CreateChild("PropertyGroup");
+    }
+
+    bool NETCSProject::GetRelativeProjectPath(const String& fromPath, const String& toPath, String& output)
+    {
+        String path = fromPath;
+        ReplacePathStrings(path);
+        path = GetSanitizedPath(path);
 
-		// Configuration
-		XMLElement config = pgroup.CreateChild("Configuration");
-		config.SetAttribute("Condition", " '$(Configuration)' == '' ");
-		config.SetValue("Debug");
+        String relativePath;
 
-		// Platform
-		XMLElement platform = pgroup.CreateChild("Platform");
-		platform.SetAttribute("Condition", " '$(Platform)' == '' ");
-		platform.SetValue("AnyCPU");
+        if (GetRelativePath(projectPath_, GetPath(path), relativePath))
+        {
+            path = relativePath + GetFileName(path) + GetExtension(path);
 
-		// ProjectGuid
-		XMLElement guid = pgroup.CreateChild("ProjectGuid");
-		guid.SetValue("{" + projectGuid_ + "}");
-
-		// OutputType
-		XMLElement outputType = pgroup.CreateChild("OutputType");
-		outputType.SetValue(outputType_);
-
-		pgroup.CreateChild("AppDesignerFolder").SetValue("Properties");
+            output = path;
 
-		// RootNamespace
-		XMLElement rootNamespace = pgroup.CreateChild("RootNamespace");
-		rootNamespace.SetValue(rootNamespace_);
+            return true;
+        }
 
-		// AssemblyName
-		XMLElement assemblyName = pgroup.CreateChild("AssemblyName");
-		assemblyName.SetValue(assemblyName_);
+        output = fromPath;
 
-		pgroup.CreateChild("FileAlignment").SetValue("512");
+        return false;
 
-		if (projectTypeGuids_.Size())
-		{
-			pgroup.CreateChild("ProjectTypeGuids").SetValue(String::Joined(projectTypeGuids_, ";"));
-		}
+    }
 
-		if (SupportsDesktop())
-		{
-			pgroup.CreateChild("TargetFrameworkVersion").SetValue("v4.5");
-		}
-		else
-		{
-			pgroup.CreateChild("ProductVersion").SetValue("8.0.30703");
-			pgroup.CreateChild("SchemaVersion").SetValue("2.0");
-
-			pgroup.CreateChild("TargetFrameworkVersion").SetValue("v6.0");
-
-			if (SupportsPlatform("android"))
-			{
-
-				if (!projectTypeGuids_.Size())
-				{
-					pgroup.CreateChild("ProjectTypeGuids").SetValue("{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}");
-				}
-
-				pgroup.CreateChild("AndroidUseLatestPlatformSdk").SetValue("True");
+    void NETCSProject::CreateMainPropertyGroup(XMLElement& projectRoot)
+    {
+        XMLElement pgroup = projectRoot.CreateChild("PropertyGroup");
 
-				if (!androidApplication_)
-				{
-					// 10368E6C-D01B-4462-8E8B-01FC667A7035 is a binding library
-					if (!projectTypeGuids_.Contains("{10368E6C-D01B-4462-8E8B-01FC667A7035}"))
-						pgroup.CreateChild("GenerateSerializationAssemblies").SetValue("Off");
-				}
-				else
-				{
-					// Android Application
+        // Configuration
+        XMLElement config = pgroup.CreateChild("Configuration");
+        config.SetAttribute("Condition", " '$(Configuration)' == '' ");
+        config.SetValue("Debug");
+
+        // Platform
+        XMLElement platform = pgroup.CreateChild("Platform");
+        platform.SetAttribute("Condition", " '$(Platform)' == '' ");
+        if (playerApplication_ && SupportsPlatform("ios"))
+            platform.SetValue("iPhone");
+        else
+            platform.SetValue("AnyCPU");
+
+        // ProjectGuid
+        XMLElement guid = pgroup.CreateChild("ProjectGuid");
+        guid.SetValue("{" + projectGuid_ + "}");
+
+        // OutputType
+        XMLElement outputType = pgroup.CreateChild("OutputType");
+        outputType.SetValue(outputType_);
+
+        pgroup.CreateChild("AppDesignerFolder").SetValue("Properties");
+
+        // RootNamespace
+        XMLElement rootNamespace = pgroup.CreateChild("RootNamespace");
+        rootNamespace.SetValue(rootNamespace_);
+
+        // AssemblyName
+        XMLElement assemblyName = pgroup.CreateChild("AssemblyName");
+        assemblyName.SetValue(assemblyName_);
+
+        pgroup.CreateChild("FileAlignment").SetValue("512");
+
+        if (projectTypeGuids_.Size())
+        {
+            pgroup.CreateChild("ProjectTypeGuids").SetValue(String::Joined(projectTypeGuids_, ";"));
+        }
+
+        if (SupportsDesktop())
+        {
+            pgroup.CreateChild("TargetFrameworkVersion").SetValue("v4.5");
+        }
+        else
+        {
+            pgroup.CreateChild("ProductVersion").SetValue("8.0.30703");
+            pgroup.CreateChild("SchemaVersion").SetValue("2.0");
+
+            if (SupportsPlatform("ios"))
+            {
+                pgroup.CreateChild("IPhoneResourcePrefix").SetValue("Resources");
+            }
+            else
+            {
+                pgroup.CreateChild("TargetFrameworkVersion").SetValue("v6.0");
+            }
+
+            if (SupportsPlatform("android"))
+            {
+
+                if (!projectTypeGuids_.Size())
+                {
+                    pgroup.CreateChild("ProjectTypeGuids").SetValue("{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}");
+                }
+
+                pgroup.CreateChild("AndroidUseLatestPlatformSdk").SetValue("True");
+
+                if (!androidApplication_)
+                {
+                    // 10368E6C-D01B-4462-8E8B-01FC667A7035 is a binding library
+                    if (!projectTypeGuids_.Contains("{10368E6C-D01B-4462-8E8B-01FC667A7035}"))
+                        pgroup.CreateChild("GenerateSerializationAssemblies").SetValue("Off");
+                }
+                else
+                {
+                    // Android Application
+
+                    pgroup.CreateChild("AndroidApplication").SetValue("true");
+
+                    // AndroidManifest.xml must reside in Properties/AndroidManifest.xml, which introduces sync issues :/
+
+                    pgroup.CreateChild("AndroidManifest").SetValue("Properties\\AndroidManifest.xml");
+
+                    FileSystem* fileSystem = GetSubsystem<FileSystem>();
+
+                    String manifestSourceFile = "$ATOMIC_PROJECT_ROOT$/Project/AtomicNET/Platforms/Android/Properties/AndroidManifest.xml";
+                    ReplacePathStrings(manifestSourceFile);
+                    manifestSourceFile = GetSanitizedPath(manifestSourceFile);
+
+                    if (fileSystem->FileExists(manifestSourceFile))
+                    {
+                        String manifestDest = GetSanitizedPath(projectPath_ + "Properties/");
+
+                        if (!fileSystem->DirExists(manifestDest))
+                        {
+                            fileSystem->CreateDirs(GetSanitizedPath(projectGen_->GetAtomicProjectPath()), ToString("/AtomicNET/Solution/%s/Properties/", name_.CString()));
+                        }
+
+                        if (fileSystem->DirExists(manifestDest))
+                        {
+                            if (!fileSystem->Copy(manifestSourceFile, manifestDest + "AndroidManifest.xml"))
+                            {
+                                ATOMIC_LOGERRORF("Unable to copy AndroidManifest from %s to %s", manifestSourceFile.CString(), manifestDest.CString());
+                            }
+                        }
+                        else
+                        {
+                            ATOMIC_LOGERRORF("Unable to create folder %s for AndroidManifest.xml", manifestDest.CString());
+                        }
+
+                    }
+                    else
+                    {
+                        ATOMIC_LOGERRORF("No AndroidManifest.xml, project will not deploy (%s)", manifestSourceFile.CString());
+                    }
+
+                    String relativePath;
+                    if (GetRelativeProjectPath("$ATOMIC_PROJECT_ROOT$/Project/AtomicNET/Platforms/Android/Resources/Resource.Designer.cs", projectPath_, relativePath))
+                    {
+                        relativePath.Replace("/", "\\");
+                        pgroup.CreateChild("AndroidResgenFile").SetValue(relativePath);
+                    }
+                    else
+                    {
+                        ATOMIC_LOGERROR("Unabled to get relative path for AndroidResgenFile");
+                    }
+
+                    pgroup.CreateChild("GenerateSerializationAssemblies").SetValue("Off");
+                }
+
+            }
+        }
+
+        if (targetFrameworkProfile_.Length())
+        {
+            pgroup.CreateChild("TargetFrameworkProfile").SetValue(targetFrameworkProfile_);
+        }
+
+    }
+
+    bool NETCSProject::GenerateShared()
+    {
+        // .shproj
+        XMLElement project = xmlFile_->CreateRoot("Project");
+
+        project.SetAttribute("DefaultTargets", "Build");
+        project.SetAttribute("ToolsVersion", "14.0");
+        project.SetAttribute("DefaultTargets", "Build");
+        project.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
+
+        // Project Group
+        XMLElement projectGroup = project.CreateChild("PropertyGroup");
+        projectGroup.SetAttribute("Label", "Globals");
+        projectGroup.CreateChild("ProjectGuid").SetValue(projectGuid_);
+        projectGroup.CreateChild("MinimumVisualStudioVersion").SetValue("14.0");
+
+        XMLElement import = project.CreateChild("Import");
+        import.SetAttribute("Project", "$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props");
+        import.SetAttribute("Condition", "Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')");
+
+        import = project.CreateChild("Import");
+        import.SetAttribute("Project", "$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)\\CodeSharing\\Microsoft.CodeSharing.Common.Default.props");
+
+        import = project.CreateChild("Import");
+        import.SetAttribute("Project", "$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)\\CodeSharing\\Microsoft.CodeSharing.Common.props");
+
+        import = project.CreateChild("Import");
+        import.SetAttribute("Project", ToString("%s.projitems", name_.CString()));
+        import.SetAttribute("Label", "Shared");
+
+        import = project.CreateChild("Import");
+        import.SetAttribute("Project", "$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)\\CodeSharing\\Microsoft.CodeSharing.CSharp.targets");
+
+        String projectSource = xmlFile_->ToString();
 
-					pgroup.CreateChild("AndroidApplication").SetValue("true");
+        SharedPtr<File> output(new File(context_, GetSanitizedPath(projectPath_ + name_ + ".shproj"), FILE_WRITE));
+        output->Write(projectSource.CString(), projectSource.Length());
 
-					// AndroidManifest.xml must reside in Properties/AndroidManifest.xml, which introduces sync issues :/
+        // projitems
 
-					pgroup.CreateChild("AndroidManifest").SetValue("Properties\\AndroidManifest.xml");
+        SharedPtr<XMLFile> itemsXMLFile(new XMLFile(context_));
 
-					FileSystem* fileSystem = GetSubsystem<FileSystem>();
+        XMLElement itemsProject = itemsXMLFile->CreateRoot("Project");
+        itemsProject.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
 
-					String manifestSourceFile = "$ATOMIC_PROJECT_ROOT$/Project/AtomicNET/Platforms/Android/Properties/AndroidManifest.xml";
-					ReplacePathStrings(manifestSourceFile);
-					manifestSourceFile = GetSanitizedPath(manifestSourceFile);
+        XMLElement propertyGroup = itemsProject.CreateChild("PropertyGroup");
+        propertyGroup.CreateChild("MSBuildAllProjects").SetValue("$(MSBuildAllProjects);$(MSBuildThisFileFullPath)");
+        propertyGroup.CreateChild("HasSharedItems").SetValue("true");
+        propertyGroup.CreateChild("SharedGUID").SetValue(projectGuid_);
 
-					if (fileSystem->FileExists(manifestSourceFile))
-					{
-						String manifestDest = GetSanitizedPath(projectPath_ + "Properties/");
+        propertyGroup = itemsProject.CreateChild("PropertyGroup");
+        propertyGroup.SetAttribute("Label", "Configuration");
+        propertyGroup.CreateChild("Import_RootNamespace").SetValue("AtomicEngine");
 
-						if (!fileSystem->DirExists(manifestDest))
-						{
-							fileSystem->CreateDirs(GetSanitizedPath(projectGen_->GetAtomicProjectPath()), ToString("/AtomicNET/Solution/%s/Properties/", name_.CString()));
-						}
+        CreateCompileItemGroup(itemsProject);
 
-						if (fileSystem->DirExists(manifestDest))
-						{
-							if (!fileSystem->Copy(manifestSourceFile, manifestDest + "AndroidManifest.xml"))
-							{
-								ATOMIC_LOGERRORF("Unable to copy AndroidManifest from %s to %s", manifestSourceFile.CString(), manifestDest.CString());
-							}
-						}
-						else
-						{
-							ATOMIC_LOGERRORF("Unable to create folder %s for AndroidManifest.xml", manifestDest.CString());
-						}
-
-					}
-					else
-					{
-						ATOMIC_LOGERRORF("No AndroidManifest.xml, project will not deploy (%s)", manifestSourceFile.CString());
-					}
-
-					String relativePath;
-					if (GetRelativeProjectPath("$ATOMIC_PROJECT_ROOT$/Project/AtomicNET/Platforms/Android/Resources/Resource.Designer.cs", projectPath_, relativePath))
-					{
-						relativePath.Replace("/", "\\");
-						pgroup.CreateChild("AndroidResgenFile").SetValue(relativePath);
-					}
-					else
-					{
-						ATOMIC_LOGERROR("Unabled to get relative path for AndroidResgenFile");
-					}
-
-					pgroup.CreateChild("GenerateSerializationAssemblies").SetValue("Off");
-				}
-
-			}
-		}
-
-		if (targetFrameworkProfile_.Length())
-		{
-			pgroup.CreateChild("TargetFrameworkProfile").SetValue(targetFrameworkProfile_);
-		}
-
-	}
-
-	bool NETCSProject::GenerateShared()
-	{
-		// .shproj
-		XMLElement project = xmlFile_->CreateRoot("Project");
-
-		project.SetAttribute("DefaultTargets", "Build");
-		project.SetAttribute("ToolsVersion", "14.0");
-		project.SetAttribute("DefaultTargets", "Build");
-		project.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
-
-		// Project Group
-		XMLElement projectGroup = project.CreateChild("PropertyGroup");
-		projectGroup.SetAttribute("Label", "Globals");
-		projectGroup.CreateChild("ProjectGuid").SetValue(projectGuid_);
-		projectGroup.CreateChild("MinimumVisualStudioVersion").SetValue("14.0");
-
-		XMLElement import = project.CreateChild("Import");
-		import.SetAttribute("Project", "$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props");
-		import.SetAttribute("Condition", "Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')");
-
-		import = project.CreateChild("Import");
-		import.SetAttribute("Project", "$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)\\CodeSharing\\Microsoft.CodeSharing.Common.Default.props");
-
-		import = project.CreateChild("Import");
-		import.SetAttribute("Project", "$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)\\CodeSharing\\Microsoft.CodeSharing.Common.props");
-
-		import = project.CreateChild("Import");
-		import.SetAttribute("Project", ToString("%s.projitems", name_.CString()));
-		import.SetAttribute("Label", "Shared");
-
-		import = project.CreateChild("Import");
-		import.SetAttribute("Project", "$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)\\CodeSharing\\Microsoft.CodeSharing.CSharp.targets");
-
-		String projectSource = xmlFile_->ToString();
+        String itemSource = itemsXMLFile->ToString();
 
-        SharedPtr<File> output(new File(context_, GetSanitizedPath(projectPath_ + name_ + ".shproj"), FILE_WRITE));
-		output->Write(projectSource.CString(), projectSource.Length());
+        SharedPtr<File> itemsOutput(new File(context_, GetSanitizedPath(projectPath_ + name_ + ".projitems"), FILE_WRITE));
+        itemsOutput->Write(itemSource.CString(), itemSource.Length());
 
-		// projitems
+        return true;
+    }
 
-		SharedPtr<XMLFile> itemsXMLFile(new XMLFile(context_));
+    bool NETCSProject::GenerateStandard()
+    {
+        ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+        FileSystem* fileSystem = GetSubsystem<FileSystem>();
+        NETSolution* solution = projectGen_->GetSolution();
 
-		XMLElement itemsProject = itemsXMLFile->CreateRoot("Project");
-		itemsProject.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
+        XMLElement project = xmlFile_->CreateRoot("Project");
 
-		XMLElement propertyGroup = itemsProject.CreateChild("PropertyGroup");
-		propertyGroup.CreateChild("MSBuildAllProjects").SetValue("$(MSBuildAllProjects);$(MSBuildThisFileFullPath)");
-		propertyGroup.CreateChild("HasSharedItems").SetValue("true");
-		propertyGroup.CreateChild("SharedGUID").SetValue(projectGuid_);
+        project.SetAttribute("DefaultTargets", "Build");
+        project.SetAttribute("ToolsVersion", "14.0");
+        project.SetAttribute("DefaultTargets", "Build");
+        project.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
 
-		propertyGroup = itemsProject.CreateChild("PropertyGroup");
-		propertyGroup.SetAttribute("Label", "Configuration");
-		propertyGroup.CreateChild("Import_RootNamespace").SetValue("AtomicEngine");
+        XMLElement import = project.CreateChild("Import");
+        import.SetAttribute("Project", "$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props");
+        import.SetAttribute("Condition", "Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')");
 
-		CreateCompileItemGroup(itemsProject);
+        CreateMainPropertyGroup(project);
+        CreateDebugPropertyGroup(project);
+        CreateReleasePropertyGroup(project);
+        CreateReferencesItemGroup(project);
+        CreateProjectReferencesItemGroup(project);
+        CreateCompileItemGroup(project);
+        CreatePackagesItemGroup(project);
 
-		String itemSource = itemsXMLFile->ToString();
+        if (SupportsPlatform("android"))
+        {
+            CreateAndroidItems(project);
+        }
 
-        SharedPtr<File> itemsOutput(new File(context_, GetSanitizedPath(projectPath_ + name_ + ".projitems"), FILE_WRITE));
-		itemsOutput->Write(itemSource.CString(), itemSource.Length());
+        if (SupportsPlatform("ios"))
+        {
+            CreateIOSItems(project);
+        }
 
-		return true;
-	}
 
-	bool NETCSProject::GenerateStandard()
-	{
-		ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
-		FileSystem* fileSystem = GetSubsystem<FileSystem>();
-		NETSolution* solution = projectGen_->GetSolution();
+        if (SupportsDesktop() && !GetIsPCL())
+            project.CreateChild("Import").SetAttribute("Project", "$(MSBuildToolsPath)\\Microsoft.CSharp.targets");
 
-		XMLElement project = xmlFile_->CreateRoot("Project");
+        if (outputType_.ToLower() == "exe" || androidApplication_)
+        {
+            CreateApplicationItems(project);
+        }
 
-		project.SetAttribute("DefaultTargets", "Build");
-		project.SetAttribute("ToolsVersion", "14.0");
-		project.SetAttribute("DefaultTargets", "Build");
-		project.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
+        if (!GetIsPCL() && !sharedReferences_.Size() && outputType_ != "Shared")
+            CreateAssemblyInfo();
 
-		XMLElement import = project.CreateChild("Import");
-		import.SetAttribute("Project", "$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props");
-		import.SetAttribute("Condition", "Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')");
+        const String& atomicProjectPath = projectGen_->GetAtomicProjectPath();
 
-		CreateMainPropertyGroup(project);
-		CreateDebugPropertyGroup(project);
-		CreateReleasePropertyGroup(project);
-		CreateReferencesItemGroup(project);
-		CreateProjectReferencesItemGroup(project);
-		CreateCompileItemGroup(project);
-		CreatePackagesItemGroup(project);
+        if (atomicProjectPath.Length())
+        {
+            // Create the AtomicProject.csproj.user file if it doesn't exist
 
-		if (SupportsPlatform("android"))
-		{
-			CreateAndroidItems(project);
-		}
+            String userSettingsFilename = projectPath_ + name_ + ".csproj.user";
 
-		if (SupportsDesktop() && !GetIsPCL())
-			project.CreateChild("Import").SetAttribute("Project", "$(MSBuildToolsPath)\\Microsoft.CSharp.targets");
+            if (!fileSystem->FileExists(userSettingsFilename))
+            {
+                SharedPtr<XMLFile> userSettings(new XMLFile(context_));
 
-		if (outputType_.ToLower() == "exe" || androidApplication_)
-		{
-			CreateApplicationItems(project);
-		}
+                XMLElement project = userSettings->CreateRoot("Project");
 
-		if (!GetIsPCL() && !sharedReferences_.Size() && outputType_ != "Shared")
-			CreateAssemblyInfo();
+                project.SetAttribute("ToolsVersion", "14.0");
+                project.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
 
-		const String& atomicProjectPath = projectGen_->GetAtomicProjectPath();
+                StringVector configs;
+                configs.Push("Debug");
+                configs.Push("Release");
 
-		if (atomicProjectPath.Length())
-		{
-			// Create the AtomicProject.csproj.user file if it doesn't exist
+                for (unsigned i = 0; i < configs.Size(); i++)
+                {
+                    String cfg = configs[i];
 
-			String userSettingsFilename = projectPath_ + name_ + ".csproj.user";
+                    XMLElement propertyGroup = project.CreateChild("PropertyGroup");
+                    propertyGroup.SetAttribute("Condition", ToString("'$(Configuration)|$(Platform)' == '%s|AnyCPU'", cfg.CString()));
 
-			if (!fileSystem->FileExists(userSettingsFilename))
-			{
-				SharedPtr<XMLFile> userSettings(new XMLFile(context_));
+                    String startArguments;
 
-				XMLElement project = userSettings->CreateRoot("Project");
-
-				project.SetAttribute("ToolsVersion", "14.0");
-				project.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
+#ifndef ATOMIC_DEV_BUILD
+                    startArguments += ToString("--resourcePrefix \"%s\" ", (fileSystem->GetProgramDir() + "Resources/").CString());
+#endif
 
-				StringVector configs;
-				configs.Push("Debug");
-				configs.Push("Release");
+                    propertyGroup.CreateChild("StartAction").SetValue("Project");
 
-				for (unsigned i = 0; i < configs.Size(); i++)
-				{
-					String cfg = configs[i];
+                    startArguments += ToString("--project \"%s\"", atomicProjectPath.CString());
 
-					XMLElement propertyGroup = project.CreateChild("PropertyGroup");
-					propertyGroup.SetAttribute("Condition", ToString("'$(Configuration)|$(Platform)' == '%s|AnyCPU'", cfg.CString()));
+                    propertyGroup.CreateChild("StartArguments").SetValue(startArguments);
 
-					String startArguments;
+                }
 
-#ifndef ATOMIC_DEV_BUILD
-					startArguments += ToString("--resourcePrefix \"%s\" ", (fileSystem->GetProgramDir() + "Resources/").CString());
-#endif
+                String userSettingsSource = userSettings->ToString();
+                SharedPtr<File> output(new File(context_, GetSanitizedPath(userSettingsFilename), FILE_WRITE));
+                output->Write(userSettingsSource.CString(), userSettingsSource.Length());
+                output->Close();
 
-					propertyGroup.CreateChild("StartAction").SetValue("Project");
+            }
 
-					startArguments += ToString("--project \"%s\"", atomicProjectPath.CString());
+        }
 
-					propertyGroup.CreateChild("StartArguments").SetValue(startArguments);
+        for (unsigned i = 0; i < sharedReferences_.Size(); i++)
+        {
+            NETCSProject* sharedProject = projectGen_->GetCSProjectByName(sharedReferences_[i]);
 
-				}
+            if (!sharedProject)
+            {
+                ATOMIC_LOGERRORF("Unable to get shared project %s", sharedReferences_[i].CString());
+                continue;
+            }
 
-				String userSettingsSource = userSettings->ToString();
-                SharedPtr<File> output(new File(context_, GetSanitizedPath(userSettingsFilename), FILE_WRITE));
-				output->Write(userSettingsSource.CString(), userSettingsSource.Length());
-				output->Close();
+            String path = sharedProject->projectPath_ + sharedReferences_[i] + ".projitems";
+            String relativePath;
+            if (GetRelativePath(projectPath_, GetPath(path), relativePath))
+            {
+                path = relativePath + GetFileName(path) + GetExtension(path);
+            }
 
-			}
+            XMLElement shared = project.CreateChild("Import");
+            shared.SetAttribute("Project", path);
+            shared.SetAttribute("Label", "Shared");
+        }
 
-		}
+        for (unsigned i = 0; i < importProjects_.Size(); i++)
+        {
+            project.CreateChild("Import").SetAttribute("Project", importProjects_[i].CString());
+        }
 
-		for (unsigned i = 0; i < sharedReferences_.Size(); i++)
-		{
-			NETCSProject* sharedProject = projectGen_->GetCSProjectByName(sharedReferences_[i]);
+        // Have to come after the imports, so AfterBuild exists
 
-			if (!sharedProject)
-			{
-				ATOMIC_LOGERRORF("Unable to get shared project %s", sharedReferences_[i].CString());
-				continue;
-			}
+        String projectName = "AtomicProject";
 
-			String path = sharedProject->projectPath_ + sharedReferences_[i] + ".projitems";
-			String relativePath;
-			if (GetRelativePath(projectPath_, GetPath(path), relativePath))
-			{
-				path = relativePath + GetFileName(path) + GetExtension(path);
-			}
+        if (projectGen_->GetProjectSettings())
+            projectName = projectGen_->GetProjectSettings()->GetName();
 
-			XMLElement shared = project.CreateChild("Import");
-			shared.SetAttribute("Project", path);
-			shared.SetAttribute("Label", "Shared");
-		}
+        if (name_ == projectName)
+        {
+            XMLElement afterBuild = project.CreateChild("Target");
+            afterBuild.SetAttribute("Name", "AfterBuild");
 
-		for (unsigned i = 0; i < importProjects_.Size(); i++)
-		{
-			project.CreateChild("Import").SetAttribute("Project", importProjects_[i].CString());
-		}
+            XMLElement copy = afterBuild.CreateChild("Copy");
+            copy.SetAttribute("SourceFiles", "$(TargetPath)");
 
-		// Have to come after the imports, so AfterBuild exists
+            String destPath = projectPath_ + "../../../Resources/";
+            String relativePath;
 
-		String projectName = "AtomicProject";
+            String resourceDir = AddTrailingSlash(atomicProjectPath) + "Resources/";
 
-		if (projectGen_->GetProjectSettings())
-			projectName = projectGen_->GetProjectSettings()->GetName();
+            if (GetRelativePath(projectPath_, resourceDir, relativePath))
+            {
+                destPath = AddTrailingSlash(relativePath);
+            }
 
-		if (name_ == projectName)
-		{
-			XMLElement afterBuild = project.CreateChild("Target");
-			afterBuild.SetAttribute("Name", "AfterBuild");
+            copy.SetAttribute("DestinationFolder", destPath);
 
-			XMLElement copy = afterBuild.CreateChild("Copy");
-			copy.SetAttribute("SourceFiles", "$(TargetPath)");
+        }
 
-			String destPath = projectPath_ + "../../../Resources/";
-			String relativePath;
 
-			String resourceDir = AddTrailingSlash(atomicProjectPath) + "Resources/";
+        String projectSource = xmlFile_->ToString();
 
-			if (GetRelativePath(projectPath_, resourceDir, relativePath))
-			{
-				destPath = AddTrailingSlash(relativePath);
-			}
+        SharedPtr<File> output(new File(context_, GetSanitizedPath(projectPath_ + name_ + ".csproj"), FILE_WRITE));
+        output->Write(projectSource.CString(), projectSource.Length());
 
-			copy.SetAttribute("DestinationFolder", destPath);
+        return true;
+    }
 
-		}
+    bool NETCSProject::Generate()
+    {
+        FileSystem* fileSystem = GetSubsystem<FileSystem>();
+        NETSolution* solution = projectGen_->GetSolution();
 
+        projectPath_ = solution->GetOutputPath() + name_ + "/";
 
-		String projectSource = xmlFile_->ToString();
+        if (!CreateProjectFolder(projectPath_))
+            return false;
 
-        SharedPtr<File> output(new File(context_, GetSanitizedPath(projectPath_ + name_ + ".csproj"), FILE_WRITE));
-		output->Write(projectSource.CString(), projectSource.Length());
+        if (!CreateProjectFolder(projectPath_ + "Properties"))
+            return false;
 
-		return true;
-	}
+        if (outputType_ == "Shared")
+        {
+            return GenerateShared();
+        }
 
-	bool NETCSProject::Generate()
-	{
-		FileSystem* fileSystem = GetSubsystem<FileSystem>();
-		NETSolution* solution = projectGen_->GetSolution();
+        return GenerateStandard();
 
-		projectPath_ = solution->GetOutputPath() + name_ + "/";
+    }
 
-		if (!CreateProjectFolder(projectPath_))
-			return false;
+    bool NETCSProject::Load(const JSONValue& root)
+    {
+        name_ = root["name"].GetString();
 
-		if (!CreateProjectFolder(projectPath_ + "Properties"))
-			return false;
+        projectGuid_ = root["projectGuid"].GetString();
 
-		if (outputType_ == "Shared")
-		{
-			return GenerateShared();
-		}
+        if (!projectGuid_.Length())
+        {
+            ATOMIC_LOGINFOF("GUID not provided for project %s, generating one", name_.CString());
+            projectGuid_ = projectGen_->GenerateUUID();
+        }
 
-		return GenerateStandard();
+        outputType_ = root["outputType"].GetString();
 
-	}
+        androidApplication_ = root["androidApplication"].GetBool();
+        playerApplication_ = root["playerApplication"].GetBool();
 
-	bool NETCSProject::Load(const JSONValue& root)
-	{
-		name_ = root["name"].GetString();
+        rootNamespace_ = root["rootNamespace"].GetString();
+        assemblyName_ = root["assemblyName"].GetString();
+        assemblyOutputPath_ = root["assemblyOutputPath"].GetString();
+        ReplacePathStrings(assemblyOutputPath_);
+        assemblyOutputPath_ = GetSanitizedPath(assemblyOutputPath_);
 
-		projectGuid_ = root["projectGuid"].GetString();
+        assemblySearchPaths_ = root["assemblySearchPaths"].GetString();
+        ReplacePathStrings(assemblySearchPaths_);
+        assemblySearchPaths_ = GetSanitizedPath(assemblySearchPaths_);
 
-		if (!projectGuid_.Length())
-		{
-			ATOMIC_LOGINFOF("GUID not provided for project %s, generating one", name_.CString());
-			projectGuid_ = projectGen_->GenerateUUID();
-		}
+        const JSONArray& platforms = root["platforms"].GetArray();
 
-		outputType_ = root["outputType"].GetString();
+        for (unsigned i = 0; i < platforms.Size(); i++)
+        {
+            String platform = platforms[i].GetString();
+            platforms_.Push(platform.ToLower());
+        }
 
-		androidApplication_ = root["androidApplication"].GetBool();
-		playerApplication_ = root["playerApplication"].GetBool();
+        const JSONArray& references = root["references"].GetArray();
 
-		rootNamespace_ = root["rootNamespace"].GetString();
-		assemblyName_ = root["assemblyName"].GetString();
-		assemblyOutputPath_ = root["assemblyOutputPath"].GetString();
-		ReplacePathStrings(assemblyOutputPath_);
-		assemblyOutputPath_ = GetSanitizedPath(assemblyOutputPath_);
+        for (unsigned i = 0; i < references.Size(); i++)
+        {
+            String reference = references[i].GetString();
+            ReplacePathStrings(reference);
+            references_.Push(reference);
+        }
 
-		assemblySearchPaths_ = root["assemblySearchPaths"].GetString();
-		ReplacePathStrings(assemblySearchPaths_);
-		assemblySearchPaths_ = GetSanitizedPath(assemblySearchPaths_);
+        const JSONArray& packages = root["packages"].GetArray();
 
-		const JSONArray& platforms = root["platforms"].GetArray();
+        for (unsigned i = 0; i < packages.Size(); i++)
+        {
+            String package = packages[i].GetString();
 
-		for (unsigned i = 0; i < platforms.Size(); i++)
-		{
-			String platform = platforms[i].GetString();
-			platforms_.Push(platform.ToLower());
-		}
+            if (packages_.Find(package) != packages_.End())
+            {
+                ATOMIC_LOGERRORF("Duplicate package found %s", package.CString());
+                continue;
+            }
 
-		const JSONArray& references = root["references"].GetArray();
+            projectGen_->GetSolution()->RegisterPackage(package);
 
-		for (unsigned i = 0; i < references.Size(); i++)
-		{
-			String reference = references[i].GetString();
-			ReplacePathStrings(reference);
-			references_.Push(reference);
-		}
+            packages_.Push(package);
+        }
 
-		const JSONArray& packages = root["packages"].GetArray();
+        const JSONArray& sources = root["sources"].GetArray();
 
-		for (unsigned i = 0; i < packages.Size(); i++)
-		{
-			String package = packages[i].GetString();
+        for (unsigned i = 0; i < sources.Size(); i++)
+        {
+            String source = sources[i].GetString();
+            ReplacePathStrings(source);
+            sourceFolders_.Push(AddTrailingSlash(source));
+        }
 
-			if (packages_.Find(package) != packages_.End())
-			{
-				ATOMIC_LOGERRORF("Duplicate package found %s", package.CString());
-				continue;
-			}
+        const JSONArray& defineConstants = root["defineConstants"].GetArray();
 
-			projectGen_->GetSolution()->RegisterPackage(package);
+        for (unsigned i = 0; i < defineConstants.Size(); i++)
+        {
+            defineConstants_.Push(defineConstants[i].GetString());
+        }
 
-			packages_.Push(package);
-		}
+        const JSONArray& projectTypeGuids = root["projectTypeGuids"].GetArray();
 
-		const JSONArray& sources = root["sources"].GetArray();
+        for (unsigned i = 0; i < projectTypeGuids.Size(); i++)
+        {
+            String guid = projectTypeGuids[i].GetString();
+            projectTypeGuids_.Push(ToString("{%s}", guid.CString()));
+        }
 
-		for (unsigned i = 0; i < sources.Size(); i++)
-		{
-			String source = sources[i].GetString();
-			ReplacePathStrings(source);
-			sourceFolders_.Push(AddTrailingSlash(source));
-		}
+        const JSONArray& importProjects = root["importProjects"].GetArray();
 
-		const JSONArray& defineConstants = root["defineConstants"].GetArray();
+        for (unsigned i = 0; i < importProjects.Size(); i++)
+        {
+            importProjects_.Push(importProjects[i].GetString());
+        }
 
-		for (unsigned i = 0; i < defineConstants.Size(); i++)
-		{
-			defineConstants_.Push(defineConstants[i].GetString());
-		}
+        const JSONArray& libraryProjectZips = root["libraryProjectZips"].GetArray();
 
-		const JSONArray& projectTypeGuids = root["projectTypeGuids"].GetArray();
+        for (unsigned i = 0; i < libraryProjectZips.Size(); i++)
+        {
+            String zipPath = libraryProjectZips[i].GetString();
+            ReplacePathStrings(zipPath);
+            libraryProjectZips_.Push(zipPath);
+        }
 
-		for (unsigned i = 0; i < projectTypeGuids.Size(); i++)
-		{
-			String guid = projectTypeGuids[i].GetString();
-			projectTypeGuids_.Push(ToString("{%s}", guid.CString()));
-		}
+        const JSONArray& transformFiles = root["transformFiles"].GetArray();
 
-		const JSONArray& importProjects = root["importProjects"].GetArray();
+        for (unsigned i = 0; i < transformFiles.Size(); i++)
+        {
+            String transformFile = transformFiles[i].GetString();
+            ReplacePathStrings(transformFile);
+            transformFiles_.Push(transformFile);
+        }
 
-		for (unsigned i = 0; i < importProjects.Size(); i++)
-		{
-			importProjects_.Push(importProjects[i].GetString());
-		}
+        const JSONArray& sharedReferences = root["sharedReferences"].GetArray();
 
-		const JSONArray& libraryProjectZips = root["libraryProjectZips"].GetArray();
+        for (unsigned i = 0; i < sharedReferences.Size(); i++)
+        {
+            sharedReferences_.Push(sharedReferences[i].GetString());
+        }
 
-		for (unsigned i = 0; i < libraryProjectZips.Size(); i++)
-		{
-			String zipPath = libraryProjectZips[i].GetString();
-			ReplacePathStrings(zipPath);
-			libraryProjectZips_.Push(zipPath);
-		}
+        targetFrameworkProfile_ = root["targetFrameworkProfile"].GetString();
 
-		const JSONArray& transformFiles = root["transformFiles"].GetArray();
+        // iOS
+        objcBindingApiDefinition_ = root["objcBindingApiDefinition"].GetString();
+        ReplacePathStrings(objcBindingApiDefinition_);
 
-		for (unsigned i = 0; i < transformFiles.Size(); i++)
-		{
-			String transformFile = transformFiles[i].GetString();
-			ReplacePathStrings(transformFile);
-			transformFiles_.Push(transformFile);
-		}
+        codesignEntitlements_ = root["codesignEntitlements"].GetString();
+        ReplacePathStrings(codesignEntitlements_);
 
-		const JSONArray& sharedReferences = root["sharedReferences"].GetArray();
+        infoPList_ = root["infoPList"].GetString();
+        ReplacePathStrings(infoPList_);
 
-		for (unsigned i = 0; i < sharedReferences.Size(); i++)
-		{
-			sharedReferences_.Push(sharedReferences[i].GetString());
-		}
+        return true;
+    }
 
-		targetFrameworkProfile_ = root["targetFrameworkProfile"].GetString();
+    NETSolution::NETSolution(Context* context, NETProjectGen* projectGen, bool rewrite) : NETProjectBase(context, projectGen),
+        rewriteSolution_(rewrite)
+    {
 
-		return true;
-	}
+    }
 
-	NETSolution::NETSolution(Context* context, NETProjectGen* projectGen, bool rewrite) : NETProjectBase(context, projectGen),
-		rewriteSolution_(rewrite)
-	{
+    NETSolution::~NETSolution()
+    {
 
-	}
+    }
 
-	NETSolution::~NETSolution()
-	{
+    bool NETSolution::Generate()
+    {
 
-	}
+        String slnPath = outputPath_ + name_ + ".sln";
 
-	bool NETSolution::Generate()
-	{
+        GenerateSolution(slnPath);
 
-		String slnPath = outputPath_ + name_ + ".sln";
+        return true;
+    }
 
-		GenerateSolution(slnPath);
+    void NETSolution::GenerateSolution(const String &slnPath)
+    {
+        String source = "Microsoft Visual Studio Solution File, Format Version 12.00\n";
+        source += "# Visual Studio 14\n";
+        source += "VisualStudioVersion = 14.0.25420.1\n";
+        source += "MinimumVisualStudioVersion = 10.0.40219.1\n";
 
-		return true;
-	}
+        solutionGUID_ = projectGen_->GenerateUUID();
 
-	void NETSolution::GenerateSolution(const String &slnPath)
-	{
-		String source = "Microsoft Visual Studio Solution File, Format Version 12.00\n";
-		source += "# Visual Studio 14\n";
-		source += "VisualStudioVersion = 14.0.25420.1\n";
-		source += "MinimumVisualStudioVersion = 10.0.40219.1\n";
+        PODVector<NETCSProject*> depends;
+        const Vector<SharedPtr<NETCSProject>>& projects = projectGen_->GetCSProjects();
 
-		solutionGUID_ = projectGen_->GenerateUUID();
+        for (unsigned i = 0; i < projects.Size(); i++)
+        {
+            NETCSProject* p = projects.At(i);
 
-		PODVector<NETCSProject*> depends;
-		const Vector<SharedPtr<NETCSProject>>& projects = projectGen_->GetCSProjects();
+            const String& projectName = p->GetName();
+            const String& projectGUID = p->GetProjectGUID();
 
-		for (unsigned i = 0; i < projects.Size(); i++)
-		{
-			NETCSProject* p = projects.At(i);
+            String CSharpProjectGUID = "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC";
+            String ext = "csproj";
 
-			const String& projectName = p->GetName();
-			const String& projectGUID = p->GetProjectGUID();
+            if (p->outputType_ == "Shared")
+            {
+                CSharpProjectGUID = "D954291E-2A0B-460D-934E-DC6B0785DB48";
+                ext = "shproj";
+            }
 
-			String CSharpProjectGUID = "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC";
-			String ext = "csproj";
+            source += ToString("Project(\"{%s}\") = \"%s\", \"%s\\%s.%s\", \"{%s}\"\n",
+                CSharpProjectGUID.CString(), projectName.CString(), projectName.CString(),
+                projectName.CString(), ext.CString(), projectGUID.CString());
 
-			if (p->outputType_ == "Shared")
-			{
-				CSharpProjectGUID = "D954291E-2A0B-460D-934E-DC6B0785DB48";
-				ext = "shproj";
-			}
 
-			source += ToString("Project(\"{%s}\") = \"%s\", \"%s\\%s.%s\", \"{%s}\"\n",
-				CSharpProjectGUID.CString(), projectName.CString(), projectName.CString(),
-				projectName.CString(), ext.CString(), projectGUID.CString());
+            projectGen_->GetCSProjectDependencies(p, depends);
 
+            if (depends.Size())
+            {
+                source += "\tProjectSection(ProjectDependencies) = postProject\n";
 
-			projectGen_->GetCSProjectDependencies(p, depends);
+                for (unsigned j = 0; j < depends.Size(); j++)
+                {
+                    source += ToString("\t{%s} = {%s}\n",
+                        depends[j]->GetProjectGUID().CString(), depends[j]->GetProjectGUID().CString());
+                }
 
-			if (depends.Size())
-			{
-				source += "\tProjectSection(ProjectDependencies) = postProject\n";
+                source += "\tEndProjectSection\n";
+            }
 
-				for (unsigned j = 0; j < depends.Size(); j++)
-				{
-					source += ToString("\t{%s} = {%s}\n",
-						depends[j]->GetProjectGUID().CString(), depends[j]->GetProjectGUID().CString());
-				}
+            source += "EndProject\n";
+        }
 
-				source += "\tEndProjectSection\n";
-			}
+        source += "Global\n";
 
-			source += "EndProject\n";
-		}
+        // SharedMSBuildProjectFiles
 
-		source += "Global\n";
+        source += "    GlobalSection(SharedMSBuildProjectFiles) = preSolution\n";
 
-		// SharedMSBuildProjectFiles
+        for (unsigned i = 0; i < projects.Size(); i++)
+        {
+            NETCSProject* p = projects.At(i);
 
-		source += "    GlobalSection(SharedMSBuildProjectFiles) = preSolution\n";
+            if (p->outputType_ == "Shared")
+            {
 
-		for (unsigned i = 0; i < projects.Size(); i++)
-		{
-			NETCSProject* p = projects.At(i);
+                for (unsigned j = 0; j < projects.Size(); j++)
+                {
+                    NETCSProject* p2 = projects.At(j);
 
-			if (p->outputType_ == "Shared")
-			{
+                    if (p == p2)
+                    {
+                        source += ToString("        %s\\%s.projitems*{%s}*SharedItemsImports = 13\n", p->name_.CString(), p->name_.CString(), p->projectGuid_.CString());
+                    }
+                    else
+                    {
+                        if (p2->sharedReferences_.Contains(p->name_))
+                        {
+                            source += ToString("        %s\\%s.projitems*{%s}*SharedItemsImports = 4\n", p->name_.CString(), p->name_.CString(), p2->projectGuid_.CString());
+                        }
+                    }
 
-				for (unsigned j = 0; j < projects.Size(); j++)
-				{
-					NETCSProject* p2 = projects.At(j);
+                }
 
-					if (p == p2)
-					{
-						source += ToString("        %s\\%s.projitems*{%s}*SharedItemsImports = 13\n", p->name_.CString(), p->name_.CString(), p->projectGuid_.CString());
-					}
-					else
-					{
-						if (p2->sharedReferences_.Contains(p->name_))
-						{
-							source += ToString("        %s\\%s.projitems*{%s}*SharedItemsImports = 4\n", p->name_.CString(), p->name_.CString(), p2->projectGuid_.CString());
-						}
-					}
 
-				}
+            }
+        }
 
+        source += "    EndGlobalSection\n";
 
-			}
-		}
+        source += "    GlobalSection(SolutionConfigurationPlatforms) = preSolution\n";
+        source += "        Debug|Any CPU = Debug|Any CPU\n";
+        source += "        Release|Any CPU = Release|Any CPU\n";        
+        source += "        Debug|iPhone = Debug|iPhone\n";
+        source += "        Release|iPhone = Release|iPhone\n";
+        source += "    EndGlobalSection\n";
+        source += "    GlobalSection(ProjectConfigurationPlatforms) = postSolution\n";
 
-		source += "    EndGlobalSection\n";
+        for (unsigned i = 0; i < projects.Size(); i++)
+        {
+            NETCSProject* p = projects.At(i);
 
-		source += "    GlobalSection(SolutionConfigurationPlatforms) = preSolution\n";
-		source += "        Debug|Any CPU = Debug|Any CPU\n";
-		source += "        Release|Any CPU = Release|Any CPU\n";
-		source += "    EndGlobalSection\n";
-		source += "    GlobalSection(ProjectConfigurationPlatforms) = postSolution\n";
+            if (p->outputType_ == "Shared")
+                continue;
 
-		for (unsigned i = 0; i < projects.Size(); i++)
-		{
-			NETCSProject* p = projects.At(i);
+            String cpu = "Any CPU";
+            if (p->GetIsPlayerApp() && p->SupportsPlatform("ios"))
+                cpu = "iPhone";
 
-			if (p->outputType_ == "Shared")
-				continue;
+            source += ToString("        {%s}.Debug|%s.ActiveCfg = Debug|%s\n", p->GetProjectGUID().CString(), cpu.CString(), cpu.CString());
+            source += ToString("        {%s}.Debug|%s.Build.0 = Debug|%s\n", p->GetProjectGUID().CString(), cpu.CString(), cpu.CString());
+            source += ToString("        {%s}.Release|%s.ActiveCfg = Release|%s\n", p->GetProjectGUID().CString(), cpu.CString(), cpu.CString());
+            source += ToString("        {%s}.Release|%s.Build.0 = Release|%s\n", p->GetProjectGUID().CString(), cpu.CString(), cpu.CString());
 
-			source += ToString("        {%s}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n", p->GetProjectGUID().CString());
-			source += ToString("        {%s}.Debug|Any CPU.Build.0 = Debug|Any CPU\n", p->GetProjectGUID().CString());
-			source += ToString("        {%s}.Release|Any CPU.ActiveCfg = Release|Any CPU\n", p->GetProjectGUID().CString());
-			source += ToString("        {%s}.Release|Any CPU.Build.0 = Release|Any CPU\n", p->GetProjectGUID().CString());
-		}
+            if (cpu != "iPhone" && (p->SupportsPlatform("ios", false)))
+            {                               
+                source += ToString("        {%s}.Debug|iPhone.ActiveCfg = Debug|Any CPU\n", p->GetProjectGUID().CString());
+                source += ToString("        {%s}.Debug|iPhone.Build.0 = Debug|Any CPU\n", p->GetProjectGUID().CString());
+                source += ToString("        {%s}.Release|iPhone.ActiveCfg = Release|Any CPU\n", p->GetProjectGUID().CString());
+                source += ToString("        {%s}.Release|iPhone.Build.0 = Release|Any CPU\n", p->GetProjectGUID().CString());
+            }
+        }
 
-		source += "    EndGlobalSection\n";
+        source += "    EndGlobalSection\n";
 
-		source += "EndGlobal\n";
+        source += "EndGlobal\n";
 
-		if (!rewriteSolution_)
-		{
-			FileSystem* fileSystem = GetSubsystem<FileSystem>();
-			if (fileSystem->Exists(slnPath))
-				return;
-		}
+        if (!rewriteSolution_)
+        {
+            FileSystem* fileSystem = GetSubsystem<FileSystem>();
+            if (fileSystem->Exists(slnPath))
+                return;
+        }
 
         SharedPtr<File> output(new File(context_, GetSanitizedPath(slnPath), FILE_WRITE));
-		output->Write(source.CString(), source.Length());
-		output->Close();
-	}
+        output->Write(source.CString(), source.Length());
+        output->Close();
+    }
 
-	bool NETSolution::Load(const JSONValue& root)
-	{
-		FileSystem* fs = GetSubsystem<FileSystem>();
+    bool NETSolution::Load(const JSONValue& root)
+    {
+        FileSystem* fs = GetSubsystem<FileSystem>();
 
-		name_ = root["name"].GetString();
+        name_ = root["name"].GetString();
 
-		outputPath_ = AddTrailingSlash(root["outputPath"].GetString());
+        outputPath_ = AddTrailingSlash(root["outputPath"].GetString());
 
-		ReplacePathStrings(outputPath_);
+        ReplacePathStrings(outputPath_);
 
-		// TODO: use poco mkdirs
-		if (!fs->DirExists(outputPath_))
-			fs->CreateDirsRecursive(outputPath_);
+        // TODO: use poco mkdirs
+        if (!fs->DirExists(outputPath_))
+            fs->CreateDirsRecursive(outputPath_);
 
-		return true;
-	}
+        return true;
+    }
 
-	bool NETSolution::RegisterPackage(const String& package)
-	{
-		if (packages_.Find(package) != packages_.End())
-			return false;
+    bool NETSolution::RegisterPackage(const String& package)
+    {
+        if (packages_.Find(package) != packages_.End())
+            return false;
 
-		packages_.Push(package);
+        packages_.Push(package);
 
-		return true;
-	}
+        return true;
+    }
 
-	NETProjectGen::NETProjectGen(Context* context) : Object(context),
-		rewriteSolution_(false)
-	{
+    NETProjectGen::NETProjectGen(Context* context) : Object(context),
+        rewriteSolution_(false)
+    {
 
-	}
+    }
 
-	NETProjectGen::~NETProjectGen()
-	{
+    NETProjectGen::~NETProjectGen()
+    {
 
-	}
+    }
 
-	NETCSProject* NETProjectGen::GetCSProjectByName(const String & name)
-	{
+    NETCSProject* NETProjectGen::GetCSProjectByName(const String & name)
+    {
 
-		for (unsigned i = 0; i < projects_.Size(); i++)
-		{
-			if (projects_[i]->GetName() == name)
-				return projects_[i];
-		}
+        for (unsigned i = 0; i < projects_.Size(); i++)
+        {
+            if (projects_[i]->GetName() == name)
+                return projects_[i];
+        }
 
-		return nullptr;
-	}
+        return nullptr;
+    }
 
-	bool NETProjectGen::GetCSProjectDependencies(NETCSProject* source, PODVector<NETCSProject*>& depends) const
-	{
-		depends.Clear();
+    bool NETProjectGen::GetCSProjectDependencies(NETCSProject* source, PODVector<NETCSProject*>& depends) const
+    {
+        depends.Clear();
 
-		const Vector<String>& references = source->GetReferences();
+        const Vector<String>& references = source->GetReferences();
 
-		for (unsigned i = 0; i < projects_.Size(); i++)
-		{
-			NETCSProject* pdepend = projects_.At(i);
+        for (unsigned i = 0; i < projects_.Size(); i++)
+        {
+            NETCSProject* pdepend = projects_.At(i);
 
-			if (source == pdepend)
-				continue;
+            if (source == pdepend)
+                continue;
 
-			for (unsigned j = 0; j < references.Size(); j++)
-			{
-				if (pdepend->GetName() == references[j])
-				{
-					depends.Push(pdepend);
-				}
-			}
-		}
+            for (unsigned j = 0; j < references.Size(); j++)
+            {
+                if (pdepend->GetName() == references[j])
+                {
+                    depends.Push(pdepend);
+                }
+            }
+        }
 
-		return depends.Size() != 0;
+        return depends.Size() != 0;
 
-	}
+    }
 
-	bool NETProjectGen::Generate()
-	{
-		solution_->Generate();
+    bool NETProjectGen::Generate()
+    {
+        solution_->Generate();
 
-		for (unsigned i = 0; i < projects_.Size(); i++)
-		{
-			if (!projects_[i]->Generate())
-				return false;
-		}
-		return true;
-	}
+        for (unsigned i = 0; i < projects_.Size(); i++)
+        {
+            if (!projects_[i]->Generate())
+                return false;
+        }
+        return true;
+    }
 
-	void NETProjectGen::SetRewriteSolution(bool rewrite)
-	{
-		rewriteSolution_ = rewrite;
+    void NETProjectGen::SetRewriteSolution(bool rewrite)
+    {
+        rewriteSolution_ = rewrite;
 
-		if (solution_.NotNull())
-			solution_->SetRewriteSolution(rewrite);
-	}
+        if (solution_.NotNull())
+            solution_->SetRewriteSolution(rewrite);
+    }
 
-	bool NETProjectGen::IncludeProjectOnPlatform(const JSONValue& projectRoot, const String& platform)
-	{
-		const JSONArray& platforms = projectRoot["platforms"].GetArray();
+    bool NETProjectGen::IncludeProjectOnPlatform(const JSONValue& projectRoot, const String& platform)
+    {
+        const JSONArray& platforms = projectRoot["platforms"].GetArray();
 
-		if (!platforms.Size())
-			return true; // all platforms
+        if (!platforms.Size())
+            return true; // all platforms
 
-		String scriptPlatform = platform.ToLower();
+        String scriptPlatform = platform.ToLower();
 
-		for (unsigned i = 0; i < platforms.Size(); i++)
-		{
-			String platform = platforms[i].GetString().ToLower();
+        for (unsigned i = 0; i < platforms.Size(); i++)
+        {
+            String platform = platforms[i].GetString().ToLower();
 
-			if (platform == "desktop")
-			{
-				if (scriptPlatform == "windows" || scriptPlatform == "macosx" || scriptPlatform == "linux")
-					return true;
+            if (platform == "desktop")
+            {
+                if (scriptPlatform == "windows" || scriptPlatform == "macosx" || scriptPlatform == "linux")
+                    return true;
 
-				return false;
-			}
+                return false;
+            }
 
-			if (platform == "android" && scriptPlatform != "android")
-				return false;
+            if (platform == "android" && scriptPlatform != "android")
+                return false;
 
-		}
+        }
 
-		return true;
+        return true;
 
-	}
+    }
 
-	bool NETProjectGen::LoadProject(const JSONValue &root)
-	{
+    bool NETProjectGen::LoadProject(const JSONValue &root)
+    {
 
-		solution_ = new NETSolution(context_, this, rewriteSolution_);
+        solution_ = new NETSolution(context_, this, rewriteSolution_);
 
-		solution_->Load(root["solution"]);
+        solution_->Load(root["solution"]);
 
-		const JSONValue& jprojects = root["projects"];
+        const JSONValue& jprojects = root["projects"];
 
-		if (!jprojects.IsArray() || !jprojects.Size())
-			return false;
+        if (!jprojects.IsArray() || !jprojects.Size())
+            return false;
 
-		for (unsigned i = 0; i < jprojects.Size(); i++)
-		{
-			const JSONValue& jproject = jprojects[i];
+        for (unsigned i = 0; i < jprojects.Size(); i++)
+        {
+            const JSONValue& jproject = jprojects[i];
 
-			if (!jproject.IsObject())
-				return false;
+            if (!jproject.IsObject())
+                return false;
 
-			JSONArray platforms = jproject["platforms"].GetArray();
+            JSONArray platforms = jproject["platforms"].GetArray();
 
-			if (platforms.Size())
-			{
-				bool found = false;
-				for (unsigned j = 0; j < platforms.Size(); j++)
-				{
-					if (GetSupportsPlatform(platforms[j].GetString()))
-					{
-						found = true;
-						break;
-					}
-				}
+            if (platforms.Size())
+            {
+                bool found = false;
+                for (unsigned j = 0; j < platforms.Size(); j++)
+                {
+                    if (GetSupportsPlatform(platforms[j].GetString()))
+                    {
+                        found = true;
+                        break;
+                    }
+                }
 
-				if (!found)
-				{
-					continue;
-				}
-			}
+                if (!found)
+                {
+                    continue;
+                }
+            }
 
-			// HACK!  Do not generate AtomicNETService in the AtomicProject solution
-			if (jproject["name"].GetString() == "AtomicNETService" && atomicProjectPath_.Length())
-			{
-				continue;
-			}
+            // HACK!  Do not generate AtomicNETService in the AtomicProject solution
+            if (jproject["name"].GetString() == "AtomicNETService" && atomicProjectPath_.Length())
+            {
+                continue;
+            }
 
-			SharedPtr<NETCSProject> csProject(new NETCSProject(context_, this));
+            SharedPtr<NETCSProject> csProject(new NETCSProject(context_, this));
 
-			if (!csProject->Load(jproject))
-				return false;
+            if (!csProject->Load(jproject))
+                return false;
 
-			projects_.Push(csProject);
+            projects_.Push(csProject);
 
-		}
+        }
 
-		return true;
-	}
+        return true;
+    }
 
-	bool NETProjectGen::LoadJSONProject(const String& jsonProjectPath)
-	{
-		SharedPtr<File> file(new File(context_));
+    bool NETProjectGen::LoadJSONProject(const String& jsonProjectPath)
+    {
+        SharedPtr<File> file(new File(context_));
 
         if (!file->Open(GetSanitizedPath(jsonProjectPath)))
-			return false;
-
-		String json;
-		file->ReadText(json);
-
-		JSONValue jvalue;
-
-		if (!JSONFile::ParseJSON(json, jvalue))
-			return false;
-
-		return LoadProject(jvalue);
-	}
-
-	bool NETProjectGen::LoadAtomicProject(const String& atomicProjectPath)
-	{
-		FileSystem* fileSystem = GetSubsystem<FileSystem>();
-		ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
-		ToolSystem* tsystem = GetSubsystem<ToolSystem>();
-
-		String pathname, filename, ext;
-		SplitPath(atomicProjectPath, pathname, filename, ext);
-
-		if (ext == ".atomic")
-		{
-			atomicProjectPath_ = AddTrailingSlash(pathname);
-		}
-		else
-		{
-			atomicProjectPath_ = AddTrailingSlash(atomicProjectPath);
-		}
-
-		// Do we have a loaded project?
-		if (Project* project = tsystem->GetProject())
-		{
-			// If so, use loaded project settings
-			projectSettings_ = project->GetProjectSettings();
-		}
-		else
-		{
-			// Nope, load them up
-			projectSettings_ = SharedPtr<ProjectSettings>(new ProjectSettings(context_));
-			projectSettings_->Load(atomicProjectPath_ + "Settings/Platforms.json");
-		}
+            return false;
+
+        String json;
+        file->ReadText(json);
+
+        JSONValue jvalue;
+
+        if (!JSONFile::ParseJSON(json, jvalue))
+            return false;
+
+        return LoadProject(jvalue);
+    }
+
+    bool NETProjectGen::LoadAtomicProject(const String& atomicProjectPath)
+    {
+        ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+        ToolSystem* tsystem = GetSubsystem<ToolSystem>();
+
+        String pathname, filename, ext;
+        SplitPath(atomicProjectPath, pathname, filename, ext);
+
+        if (ext == ".atomic")
+        {
+            atomicProjectPath_ = AddTrailingSlash(pathname);
+        }
+        else
+        {
+            atomicProjectPath_ = AddTrailingSlash(atomicProjectPath);
+        }
+
+        // Do we have a loaded project?
+        if (Project* project = tsystem->GetProject())
+        {
+            // If so, use loaded project settings
+            projectSettings_ = project->GetProjectSettings();
+        }
+        else
+        {
+            // Nope, load them up
+            projectSettings_ = SharedPtr<ProjectSettings>(new ProjectSettings(context_));
+            projectSettings_->Load(atomicProjectPath_ + "Settings/Project.json");
+        }
 
 #ifdef ATOMIC_DEV_BUILD
 
-		JSONValue netJSON;
+        JSONValue netJSON;
 
-		SharedPtr<File> netJSONFile(new File(context_));
+        SharedPtr<File> netJSONFile(new File(context_));
 
-		String atomicNETProject = tenv->GetRootSourceDir() + "Script/AtomicNET/AtomicNETProject.json";
+        String atomicNETProject = tenv->GetRootSourceDir() + "Script/AtomicNET/AtomicNETProject.json";
 
         if (!netJSONFile->Open(GetSanitizedPath(atomicNETProject)))
-			return false;
+            return false;
 
-		String netJSONString;
-		netJSONFile->ReadText(netJSONString);
+        String netJSONString;
+        netJSONFile->ReadText(netJSONString);
 
-		if (!JSONFile::ParseJSON(netJSONString, netJSON))
-			return false;
+        if (!JSONFile::ParseJSON(netJSONString, netJSON))
+            return false;
 #endif
 
 #ifdef ATOMIC_DEV_BUILD
 
-		String projectPath = tenv->GetRootSourceDir() + "Script/AtomicNET/AtomicProject.json";
+        String projectPath = tenv->GetRootSourceDir() + "Script/AtomicNET/AtomicProject.json";
 #else
-		String projectPath = tenv->GetAtomicNETRootDir() + "Build/Projects/AtomicProject.json";
+        String projectPath = tenv->GetAtomicNETRootDir() + "Build/Projects/AtomicProject.json";
 #endif
 
-		SharedPtr<File> file(new File(context_));
+        SharedPtr<File> file(new File(context_));
 
         if (!file->Open(GetSanitizedPath(projectPath)))
-			return false;
+            return false;
 
-		String json;
-		file->ReadText(json);
+        String json;
+        file->ReadText(json);
 
-		json.Replace("$ATOMIC_PROJECT_NAME$", projectSettings_->GetName());
+        json.Replace("$ATOMIC_PROJECT_NAME$", projectSettings_->GetName());
 
-		JSONValue jvalue;
+        JSONValue jvalue;
 
-		if (!JSONFile::ParseJSON(json, jvalue))
-			return false;
+        if (!JSONFile::ParseJSON(json, jvalue))
+            return false;
 
 #ifdef ATOMIC_DEV_BUILD
 
-		// patch projects
-		JSONArray netProjects = netJSON["projects"].GetArray();
-		JSONArray projects = jvalue["projects"].GetArray();
+        // patch projects
+        JSONArray netProjects = netJSON["projects"].GetArray();
+        JSONArray projects = jvalue["projects"].GetArray();
 
-		for (unsigned i = 0; i < projects.Size(); i++)
-		{
-			netProjects.Push(JSONValue(projects[i].GetObject()));
-		}
+        for (unsigned i = 0; i < projects.Size(); i++)
+        {
+            netProjects.Push(JSONValue(projects[i].GetObject()));
+        }
 
-		jvalue["projects"] = netProjects;
+        jvalue["projects"] = netProjects;
 
-		return LoadProject(jvalue);
+        return LoadProject(jvalue);
 
 #else
-		return LoadProject(jvalue);
+        return LoadProject(jvalue);
 #endif
 
-	}
+    }
 
-	void NETProjectGen::SetSupportedPlatforms(const StringVector& platforms)
-	{
-		projectSettings_ = SharedPtr<ProjectSettings>(new ProjectSettings(context_));
+    void NETProjectGen::SetSupportedPlatforms(const StringVector& platforms)
+    {
+        projectSettings_ = SharedPtr<ProjectSettings>(new ProjectSettings(context_));
 
-		for (unsigned i = 0; i < platforms.Size(); i++)
-		{
-			projectSettings_->AddSupportedPlatform(platforms[i]);
-		}
+        for (unsigned i = 0; i < platforms.Size(); i++)
+        {
+            projectSettings_->AddSupportedPlatform(platforms[i]);
+        }
 
-	}
+    }
 
-	bool NETProjectGen::GetSupportsPlatform(const String& platform) const
-	{
-		// If no project platform settings are loaded, always supports
-		if (projectSettings_.Null())
-		{
-			return true;
-		}
+    bool NETProjectGen::GetSupportsPlatform(const String& platform) const
+    {
+        // If no project platform settings are loaded, always supports
+        if (projectSettings_.Null())
+        {
+            return true;
+        }
 
-		return projectSettings_->GetSupportsPlatform(platform);
+        return projectSettings_->GetSupportsPlatform(platform);
 
-	}
+    }
 
-	bool NETProjectGen::GetRequiresNuGet()
-	{
-		if (solution_.Null())
-		{
-			ATOMIC_LOGERROR("NETProjectGen::GetRequiresNuGet() - called without a solution loaded");
-			return false;
-		}
+    bool NETProjectGen::GetRequiresNuGet()
+    {
+        if (solution_.Null())
+        {
+            ATOMIC_LOGERROR("NETProjectGen::GetRequiresNuGet() - called without a solution loaded");
+            return false;
+        }
 
-		return solution_->GetPackages().Size() != 0;
+        return solution_->GetPackages().Size() != 0;
 
-	}
+    }
 
 
-	String NETProjectGen::GenerateUUID()
-	{
-		Poco::UUIDGenerator& generator = Poco::UUIDGenerator::defaultGenerator();
-		Poco::UUID uuid(generator.create()); // time based
-		return String(uuid.toString().c_str()).ToUpper();
-	}
+    String NETProjectGen::GenerateUUID()
+    {
+        Poco::UUIDGenerator& generator = Poco::UUIDGenerator::defaultGenerator();
+        Poco::UUID uuid(generator.create()); // time based
+        return String(uuid.toString().c_str()).ToUpper();
+    }
 
 }

+ 47 - 36
Source/ToolCore/NETTools/NETProjectGen.h

@@ -32,7 +32,7 @@ using namespace Atomic;
 namespace ToolCore
 {
 
-	class ProjectSettings;
+    class ProjectSettings;
     class NETProjectGen;
 
     class NETProjectBase : public Object
@@ -57,7 +57,7 @@ namespace ToolCore
 
     class NETCSProject : public NETProjectBase
     {
-		friend class NETSolution;
+        friend class NETSolution;
 
         ATOMIC_OBJECT(NETCSProject, NETProjectBase)
 
@@ -74,18 +74,22 @@ namespace ToolCore
         const Vector<String>& GetReferences() const { return references_; }
         const Vector<String>& GetPackages() const { return packages_; }
 
-		bool GetIsPCL() const { return projectTypeGuids_.Contains("{786C830F-07A1-408B-BD7F-6EE04809D6DB}"); }
+        bool GetIsPCL() const { return projectTypeGuids_.Contains("{786C830F-07A1-408B-BD7F-6EE04809D6DB}"); }
+
+        bool GetIsPlayerApp() const { return playerApplication_; }
+        bool SupportsDesktop() const;
+        bool SupportsPlatform(const String& platform, bool explicitCheck = true) const;
 
         bool Generate();
 
     private:
 
-		// Portable Class Library
-		bool GenerateShared();
+        // Portable Class Library
+        bool GenerateShared();
 
-		bool GenerateStandard();
+        bool GenerateStandard();
 
-		bool GetRelativeProjectPath(const String& fromPath, const String& toPath, String& output);
+        bool GetRelativeProjectPath(const String& fromPath, const String& toPath, String& output);
 
         bool CreateProjectFolder(const String& path);
 
@@ -97,14 +101,15 @@ namespace ToolCore
         void CreateDebugPropertyGroup(XMLElement &projectRoot);
         void CreateReleasePropertyGroup(XMLElement &projectRoot);
 
-		void CreateApplicationItems(XMLElement &projectRoot);
-		void CreateAndroidItems(XMLElement &projectRoot);
+        void CreateApplicationItems(XMLElement &projectRoot);
+        void CreateAndroidItems(XMLElement &projectRoot);
+        void CreateIOSItems(XMLElement &projectRoot);
 
         void CreateAssemblyInfo();
         void GetAssemblySearchPaths(String& paths);
 
-		bool SupportsDesktop() const;
-		bool SupportsPlatform(const String& platform, bool explicitCheck = true) const;
+        void ProcessDefineConstants(StringVector& constants);
+
 
         String name_;
         String projectGuid_;
@@ -119,26 +124,32 @@ namespace ToolCore
 
         XMLElement xmlRoot_;
 
-		Vector<String> platforms_;
+        Vector<String> platforms_;
         Vector<String> references_;
         Vector<String> packages_;
         Vector<String> sourceFolders_;
 
-		Vector<String> defineConstants_;
+        Vector<String> defineConstants_;
+
+        Vector<String> projectTypeGuids_;
+        Vector<String> importProjects_;
+        Vector<String> libraryProjectZips_;
+        Vector<String> transformFiles_;
+
+        String targetFrameworkProfile_;
+        Vector<String> sharedReferences_;
 
-		Vector<String> projectTypeGuids_;
-		Vector<String> importProjects_;
-		Vector<String> libraryProjectZips_;
-		Vector<String> transformFiles_;
+        bool playerApplication_;
 
-		String targetFrameworkProfile_;
-		Vector<String> sharedReferences_;
+        // Android
+        bool androidApplication_;
 
-		bool playerApplication_;
+        // iOS
+        String objcBindingApiDefinition_;
+        String codesignEntitlements_;
+        String infoPList_;
 
-		// Android
-		bool androidApplication_;
-		
+        
     };
 
     class NETSolution : public NETProjectBase
@@ -195,7 +206,7 @@ namespace ToolCore
 
         bool GetCSProjectDependencies(NETCSProject * source, PODVector<NETCSProject*>& depends) const;
 
-		const String& GetAtomicProjectPath() const { return atomicProjectPath_; }
+        const String& GetAtomicProjectPath() const { return atomicProjectPath_; }
 
         bool Generate();
 
@@ -208,32 +219,32 @@ namespace ToolCore
         void SetRewriteSolution(bool rewrite);
 
         bool LoadJSONProject(const String& jsonProjectPath);
-		bool LoadAtomicProject(const String& atomicProjectPath);
+        bool LoadAtomicProject(const String& atomicProjectPath);
 
-		void AddGlobalDefineConstant(const String& constant) { globalDefineConstants_.Push(constant); }
-		const Vector<String>& GetGlobalDefineConstants() const { return globalDefineConstants_; }
+        void AddGlobalDefineConstant(const String& constant) { globalDefineConstants_.Push(constant); }
+        const Vector<String>& GetGlobalDefineConstants() const { return globalDefineConstants_; }
 
-		void SetSupportedPlatforms(const StringVector& platforms);
-		bool GetSupportsPlatform(const String& platform) const;
+        void SetSupportedPlatforms(const StringVector& platforms);
+        bool GetSupportsPlatform(const String& platform) const;
 
-		ProjectSettings* GetProjectSettings() { return projectSettings_; }
+        ProjectSettings* GetProjectSettings() { return projectSettings_; }
 
     private:
 
-		bool LoadProject(const JSONValue& root);
+        bool LoadProject(const JSONValue& root);
 
-		/// Returns true if a project is included on the specifed platform
-		bool IncludeProjectOnPlatform(const JSONValue& projectRoot, const String& platform);
+        /// Returns true if a project is included on the specifed platform
+        bool IncludeProjectOnPlatform(const JSONValue& projectRoot, const String& platform);
 
         // if true, the solution (sln) file will be recreated if it exists
         bool rewriteSolution_;
 
-		String atomicProjectPath_;
+        String atomicProjectPath_;
         SharedPtr<NETSolution> solution_;
-		Vector<String> globalDefineConstants_;
+        Vector<String> globalDefineConstants_;
         Vector<SharedPtr<NETCSProject>> projects_;
 
-		SharedPtr<ProjectSettings> projectSettings_;
+        SharedPtr<ProjectSettings> projectSettings_;
 
     };
 

+ 33 - 33
Source/ToolCore/NETTools/NETProjectSystem.cpp

@@ -201,33 +201,33 @@ namespace ToolCore
         }
     }
 
-	bool NETProjectSystem::GenerateResourcePak()
-	{
-		ToolSystem* tsystem = GetSubsystem<ToolSystem>();
-		Project* project = tsystem->GetProject();
-		BuildSystem* buildSystem = GetSubsystem<BuildSystem>();
+    bool NETProjectSystem::GenerateResourcePak()
+    {
+        ToolSystem* tsystem = GetSubsystem<ToolSystem>();
+        Project* project = tsystem->GetProject();
+        BuildSystem* buildSystem = GetSubsystem<BuildSystem>();
 
-		// TODO: We just use WINDOWS platform for PAK generation for now
-		Platform* platform = tsystem->GetPlatformByName("WINDOWS");
+        // TODO: We just use WINDOWS platform for PAK generation for now
+        Platform* platform = tsystem->GetPlatformByName("WINDOWS");
 
-		buildSystem->SetBuildPath(project->GetProjectPath() + "AtomicNET/Resources/");
+        buildSystem->SetBuildPath(project->GetProjectPath() + "AtomicNET/Resources/");
 
-		SharedPtr<BuildBase> buildBase(platform->NewBuild(project));
-		buildBase->SetResourcesOnly(true);
-		buildBase->SetVerbose(true);
-		buildSystem->QueueBuild(buildBase);
-		buildSystem->StartNextBuild();
+        SharedPtr<BuildBase> buildBase(platform->NewBuild(project));
+        buildBase->SetResourcesOnly(true);
+        buildBase->SetVerbose(true);
+        buildSystem->QueueBuild(buildBase);
+        buildSystem->StartNextBuild();
 
-		if (buildBase->GetBuildFailed())
-		{
-			const StringVector& errors = buildBase->GetBuildErrors();
-			ATOMIC_LOGERRORF("NETProjectSystem::GenerateSolution - Unable to Build Resources.pak: %s", errors.Size() ? errors[0].CString() : "Unknown Error");
-			return false;
-		}
+        if (buildBase->GetBuildFailed())
+        {
+            const StringVector& errors = buildBase->GetBuildErrors();
+            ATOMIC_LOGERRORF("NETProjectSystem::GenerateSolution - Unable to Build Resources.pak: %s", errors.Size() ? errors[0].CString() : "Unknown Error");
+            return false;
+        }
 
-		return true;
+        return true;
 
-	}
+    }
 
     bool NETProjectSystem::GenerateSolution()
     {
@@ -240,19 +240,19 @@ namespace ToolCore
             return false;
         }
 
-		// TODO: Generalize and move me
-		if (project->GetSupportsPlatform("android"))
-		{
-			FileSystem* fileSystem = GetSubsystem<FileSystem>();
+        // TODO: Generalize and move me
+        if (project->GetSupportsPlatform("android"))
+        {
+            FileSystem* fileSystem = GetSubsystem<FileSystem>();
 
-			if (!fileSystem->FileExists(project->GetProjectPath() + "AtomicNET/Resources/AtomicResources.pak"))
-			{
-				if (!GenerateResourcePak())
-					return false;
+            if (!fileSystem->FileExists(project->GetProjectPath() + "AtomicNET/Resources/AtomicResources.pak"))
+            {
+                if (!GenerateResourcePak())
+                    return false;
 
-			}
+            }
 
-		}
+        }
 
         SharedPtr<NETProjectGen> gen(new NETProjectGen(context_));
 
@@ -308,12 +308,12 @@ namespace ToolCore
         using namespace ProjectLoaded;
 
         String projectPath = eventData[P_PROJECTPATH].GetString();
-		Project* project = static_cast<Project*>(eventData[P_PROJECT].GetPtr());		
+        Project* project = static_cast<Project*>(eventData[P_PROJECT].GetPtr());        
         
         if (GetExtension(projectPath) == ".atomic")
             projectPath = GetParentPath(projectPath);
 
-		String projectName = project->GetProjectSettings()->GetName();
+        String projectName = project->GetProjectSettings()->GetName();
 
         solutionPath_ = AddTrailingSlash(projectPath) + "AtomicNET/Solution/" + projectName + ".sln";
         projectAssemblyPath_ = AddTrailingSlash(projectPath) + "Resources/" + projectName + ".dll";

+ 1 - 1
Source/ToolCore/NETTools/NETProjectSystem.h

@@ -63,7 +63,7 @@ namespace ToolCore
         void OpenSourceFile(const String& sourceFilePath);
 
         bool GenerateSolution();
-		bool GenerateResourcePak();
+        bool GenerateResourcePak();
 
     private:
 

+ 7 - 7
Source/ToolCore/Project/Project.cpp

@@ -52,9 +52,9 @@ Project::Project(Context* context) :
 {
     version_ = "1.0.0";
 
-	projectSettings_ = new ProjectSettings(context_);
+    projectSettings_ = new ProjectSettings(context_);
     userPrefs_ = new ProjectUserPrefs(context_);
-    buildSettings_ = new ProjectBuildSettings(context_);	
+    buildSettings_ = new ProjectBuildSettings(context_);    
 }
 
 Project::~Project()
@@ -101,13 +101,13 @@ bool Project::LoadBuildSettings()
 
 bool Project::LoadProjectSettings()
 {
-	projectSettings_->Load(GetProjectPath() + "Settings/Project.json");
-	return true;
+    projectSettings_->Load(GetProjectPath() + "Settings/Project.json");
+    return true;
 }
 
 bool Project::GetSupportsPlatform(const String& platform) const
 {
-	return projectSettings_->GetSupportsPlatform(platform);
+    return projectSettings_->GetSupportsPlatform(platform);
 }
 
 bool Project::Load(const String& fullpath)
@@ -133,14 +133,14 @@ bool Project::Load(const String& fullpath)
 
     loading_ = false;
 
-	LoadProjectSettings();
+    LoadProjectSettings();
     LoadBuildSettings();
     LoadUserPrefs();
 
     if ( true /*result*/) {
         VariantMap data;
         data[ProjectLoaded::P_PROJECTPATH] = projectFilePath_;
-		data[ProjectLoaded::P_PROJECT] = this;
+        data[ProjectLoaded::P_PROJECT] = this;
         SendEvent(E_PROJECTLOADED, data);
     }
 

+ 4 - 4
Source/ToolCore/Project/Project.h

@@ -67,14 +67,14 @@ public:
     bool IsScriptsDirOrFile(const String& fullPath);
     bool IsModulesDirOrFile(const String& fullPath);
 
-	bool GetSupportsPlatform(const String& platform) const;
+    bool GetSupportsPlatform(const String& platform) const;
 
     bool IsDirty() { return dirty_; }
     void SetDirty() { if (!loading_) dirty_ = true; }
 
     ProjectBuildSettings* GetBuildSettings() { return buildSettings_; }
     ProjectUserPrefs* GetUserPrefs() { return userPrefs_; }
-	ProjectSettings* GetProjectSettings() { return projectSettings_; }
+    ProjectSettings* GetProjectSettings() { return projectSettings_; }
 
     const String& GetProjectPath() const { return projectPath_; }
     const String& GetProjectFilePath() { return projectFilePath_; }
@@ -86,7 +86,7 @@ public:
 
     void SaveBuildSettings();
     bool LoadBuildSettings();
-	bool LoadProjectSettings();
+    bool LoadProjectSettings();
 
     void SaveUserPrefs();
     bool LoadUserPrefs();
@@ -109,7 +109,7 @@ private:
 
     SharedPtr<ProjectUserPrefs> userPrefs_;
     SharedPtr<ProjectBuildSettings> buildSettings_;
-	SharedPtr<ProjectSettings> projectSettings_;
+    SharedPtr<ProjectSettings> projectSettings_;
 
 };
 

+ 1 - 1
Source/ToolCore/Project/ProjectEvents.h

@@ -32,7 +32,7 @@ namespace ToolCore
 ATOMIC_EVENT(E_PROJECTLOADED, ProjectLoaded)
 {
     ATOMIC_PARAM(P_PROJECTPATH, ProjectPath);    // string
-	ATOMIC_PARAM(P_PROJECT, Project);    // Project *
+    ATOMIC_PARAM(P_PROJECT, Project);    // Project *
 }
 
 ATOMIC_EVENT(E_PROJECTUNLOADED, ProjectUnloaded)

+ 167 - 166
Source/ToolCore/Project/ProjectSettings.cpp

@@ -8,172 +8,173 @@
 namespace ToolCore
 {
 
-	ProjectSettings::ProjectSettings(Context* context) : Object(context),
-		desktopSettings_(new DesktopProjectSettings()),
-		androidSettings_(new AndroidProjectSettings())
-	{
-		SetDefault();
-	}
-
-	ProjectSettings::~ProjectSettings()
-	{
-
-	}
-
-	void ProjectSettings::SetDefault()
-	{
-		name_ = "AtomicProject";
-		platforms_.Clear();
-		platforms_.Push("desktop");
-	}
-
-	bool ProjectSettings::GetSupportsDesktop() const
-	{
-		return platforms_.Contains("desktop");
-	}
-
-	bool ProjectSettings::GetSupportsAndroid() const
-	{
-		return platforms_.Contains("android");
-	}
-
-	bool ProjectSettings::GetSupportsIOS() const
-	{
-		return platforms_.Contains("ios");
-	}
-
-	bool ProjectSettings::GetSupportsWeb() const
-	{
-		return platforms_.Contains("web");
-	}
-
-	bool ProjectSettings::GetSupportsPlatform(const String& platform) const
-	{
-		return platforms_.Contains(platform);
-	}
-
-	void ProjectSettings::AddSupportedPlatform(const String& platform)
-	{
-		if (!ValidPlatform(platform))
-		{
-			ATOMIC_LOGERRORF("ProjectPlatformSettings::AddSupportedPlatform - Attempting to add invalid platform: %s", platform.CString());
-			return;
-		}
-
-		if (platforms_.Contains(platform))
-			return;
-
-		platforms_.Push(platform);
-	}
-
-	bool ProjectSettings::ValidPlatform(const String& platform) const
-	{
-		if (platform == "desktop")
-			return true;
-		if (platform == "android")
-			return true;
-		if (platform == "ios")
-			return true;
-		if (platform == "linux")
-			return true;
-		if (platform == "web")
-			return true;
-
-		return false;
-
-	}
-
-	bool ProjectSettings::Load(const String& path)
-	{
-		FileSystem* fileSystem = GetSubsystem<FileSystem>();
-
-		if (!fileSystem->FileExists(path))
-		{
-			SetDefault();
-			return true;
-		}
-
-		SharedPtr<File> file(new File(context_, path));
-		if (!file->IsOpen())
-		{
-			ATOMIC_LOGERRORF("Unable to open platform settings: %s", path.CString());
-			return false;
-		}
-
-		SharedPtr<JSONFile> jsonFile(new JSONFile(context_));
-		bool result = jsonFile->Load(*file);
-		file->Close();
-
-		if (!result)
-		{
-			ATOMIC_LOGERRORF("Unable to load platform settings: %s", path.CString());
-			return false;
-		}
-
-		JSONValue root = jsonFile->GetRoot();
-		if (!root.IsObject())
-		{
-			ATOMIC_LOGERRORF("No root object in platform settings: %s", path.CString());
-			return false;
-		}
-
-		JSONArray platforms = root["platforms"].GetArray();
-
-		platforms_.Clear();
-
-		if (!platforms.Size())
-		{
-			ATOMIC_LOGERRORF("No platforms array defined in platform settings: %s, using default", path.CString());
-			SetDefault();
-		}
-		else
-		{
-			for (unsigned i = 0; i < platforms.Size(); i++)
-			{
-				const String& platform = platforms[i].GetString();
-
-				if (!ValidPlatform(platform))
-				{
-					ATOMIC_LOGERRORF("Unknown platform %s in platform settings: %s, skipping", platform.CString(), path.CString());
-					continue;
-				}
-
-				platforms_.Push(platform);
-			}
-		}
-
-		if (!platforms_.Size())
-		{
-			ATOMIC_LOGERRORF("No valif platforms defined in platform settings: %s, using default", path.CString());
-			SetDefault();
-		}
-
-		name_ = root["name"].GetString();
-
-		if (!name_.Length())
-			name_ = "AtomicProject";
-
-		desktopSettings_->Read(root);
-		androidSettings_->Read(root);
-
-		return true;
-	}
-
-	void ProjectSettings::Save(const String& path)
-	{
-		SharedPtr<JSONFile> jsonFile(new JSONFile(context_));
-
-		JSONValue& root = jsonFile->GetRoot();
-
-		SharedPtr<File> file(new File(context_, path, FILE_WRITE));
-
-		desktopSettings_->Write(root);
-		androidSettings_->Write(root);
-
-		jsonFile->Save(*file, String("   "));
-
-		file->Close();
+    ProjectSettings::ProjectSettings(Context* context) : Object(context),
+        desktopSettings_(new DesktopProjectSettings()),
+        androidSettings_(new AndroidProjectSettings())
+    {
+        SetDefault();
+    }
+
+    ProjectSettings::~ProjectSettings()
+    {
+
+    }
+
+    void ProjectSettings::SetDefault()
+    {
+        name_ = "AtomicProject";
+        platforms_.Clear();
+        platforms_.Push("desktop");
+    }
+
+    bool ProjectSettings::GetSupportsDesktop() const
+    {
+        return platforms_.Contains("desktop");
+    }
+
+    bool ProjectSettings::GetSupportsAndroid() const
+    {
+        return platforms_.Contains("android");
+    }
+
+    bool ProjectSettings::GetSupportsIOS() const
+    {
+        return platforms_.Contains("ios");
+    }
+
+    bool ProjectSettings::GetSupportsWeb() const
+    {
+        return platforms_.Contains("web");
+    }
+
+    bool ProjectSettings::GetSupportsPlatform(const String& platform) const
+    {
+        return platforms_.Contains(platform);
+    }
+
+    void ProjectSettings::AddSupportedPlatform(const String& platform)
+    {
+        if (!ValidPlatform(platform))
+        {
+            ATOMIC_LOGERRORF("ProjectPlatformSettings::AddSupportedPlatform - Attempting to add invalid platform: %s", platform.CString());
+            return;
+        }
+
+        if (platforms_.Contains(platform))
+            return;
+
+        platforms_.Push(platform);
+    }
+
+    bool ProjectSettings::ValidPlatform(const String& platform) const
+    {
+        if (platform == "desktop")
+            return true;
+        if (platform == "android")
+            return true;
+        if (platform == "ios")
+            return true;
+        if (platform == "linux")
+            return true;
+        if (platform == "web")
+            return true;
+
+        return false;
+
+    }
+
+    bool ProjectSettings::Load(const String& path)
+    {
+        FileSystem* fileSystem = GetSubsystem<FileSystem>();
+
+        if (!fileSystem->FileExists(path))
+        {
+            ATOMIC_LOGERRORF("No platform settings specified, using default: %s", path.CString());
+            SetDefault();
+            return true;
+        }
+
+        SharedPtr<File> file(new File(context_, path));
+        if (!file->IsOpen())
+        {
+            ATOMIC_LOGERRORF("Unable to open platform settings: %s", path.CString());
+            return false;
+        }
+
+        SharedPtr<JSONFile> jsonFile(new JSONFile(context_));
+        bool result = jsonFile->Load(*file);
+        file->Close();
+
+        if (!result)
+        {
+            ATOMIC_LOGERRORF("Unable to load platform settings: %s", path.CString());
+            return false;
+        }
+
+        JSONValue root = jsonFile->GetRoot();
+        if (!root.IsObject())
+        {
+            ATOMIC_LOGERRORF("No root object in platform settings: %s", path.CString());
+            return false;
+        }
+
+        JSONArray platforms = root["platforms"].GetArray();
+
+        platforms_.Clear();
+
+        if (!platforms.Size())
+        {
+            ATOMIC_LOGERRORF("No platforms array defined in platform settings: %s, using default", path.CString());
+            SetDefault();
+        }
+        else
+        {
+            for (unsigned i = 0; i < platforms.Size(); i++)
+            {
+                const String& platform = platforms[i].GetString();
+
+                if (!ValidPlatform(platform))
+                {
+                    ATOMIC_LOGERRORF("Unknown platform %s in platform settings: %s, skipping", platform.CString(), path.CString());
+                    continue;
+                }
+
+                platforms_.Push(platform);
+            }
+        }
+
+        if (!platforms_.Size())
+        {
+            ATOMIC_LOGERRORF("No valid platforms defined in platform settings: %s, using default", path.CString());
+            SetDefault();
+        }
+
+        name_ = root["name"].GetString();
+
+        if (!name_.Length())
+            name_ = "AtomicProject";
+
+        desktopSettings_->Read(root);
+        androidSettings_->Read(root);
+
+        return true;
+    }
+
+    void ProjectSettings::Save(const String& path)
+    {
+        SharedPtr<JSONFile> jsonFile(new JSONFile(context_));
+
+        JSONValue& root = jsonFile->GetRoot();
+
+        SharedPtr<File> file(new File(context_, path, FILE_WRITE));
+
+        desktopSettings_->Write(root);
+        androidSettings_->Write(root);
+
+        jsonFile->Save(*file, String("   "));
+
+        file->Close();
 
-	}
+    }
 
 }

+ 45 - 45
Source/ToolCore/Project/ProjectSettings.h

@@ -30,74 +30,74 @@ using namespace Atomic;
 namespace ToolCore
 {
 
-	class DesktopProjectSettings : public RefCounted
-	{
-		ATOMIC_REFCOUNTED(DesktopProjectSettings)
+    class DesktopProjectSettings : public RefCounted
+    {
+        ATOMIC_REFCOUNTED(DesktopProjectSettings)
 
-	public:
+    public:
 
-		DesktopProjectSettings() {}
+        DesktopProjectSettings() {}
 
-		void Write(JSONValue& parent) {}
-		void Read(JSONValue& parent) {}
+        void Write(JSONValue& parent) {}
+        void Read(JSONValue& parent) {}
 
-	private:
+    private:
 
-	};
+    };
 
-	class AndroidProjectSettings : public RefCounted
-	{
-		ATOMIC_REFCOUNTED(AndroidProjectSettings)
+    class AndroidProjectSettings : public RefCounted
+    {
+        ATOMIC_REFCOUNTED(AndroidProjectSettings)
 
-	public:
+    public:
 
-		AndroidProjectSettings() {}
+        AndroidProjectSettings() {}
 
-		void Write(JSONValue& parent) {}
-		void Read(JSONValue& parent) {}
+        void Write(JSONValue& parent) {}
+        void Read(JSONValue& parent) {}
 
-	private:
+    private:
 
-	};
+    };
 
-	class ProjectSettings : public Object
-	{
-		ATOMIC_OBJECT(ProjectSettings, Object)
+    class ProjectSettings : public Object
+    {
+        ATOMIC_OBJECT(ProjectSettings, Object)
 
-	public:
-		/// Construct.
-		ProjectSettings(Context* context);
-		/// Destruct.
-		virtual ~ProjectSettings();
+    public:
+        /// Construct.
+        ProjectSettings(Context* context);
+        /// Destruct.
+        virtual ~ProjectSettings();
 
-		DesktopProjectSettings* GetDesktopSettings() { return desktopSettings_; }
-		AndroidProjectSettings* GetAndroidPlatformSettings() { return androidSettings_; }
+        DesktopProjectSettings* GetDesktopSettings() { return desktopSettings_; }
+        AndroidProjectSettings* GetAndroidPlatformSettings() { return androidSettings_; }
 
-		bool Load(const String& path);
-		void Save(const String& path);
+        bool Load(const String& path);
+        void Save(const String& path);
 
-		const String& GetName() const { return name_;  }
+        const String& GetName() const { return name_;  }
 
-		bool ValidPlatform(const String& platform) const;
+        bool ValidPlatform(const String& platform) const;
 
-		bool GetSupportsPlatform(const String& platform) const;
-		bool GetSupportsDesktop() const;
-		bool GetSupportsAndroid() const;
-		bool GetSupportsIOS() const;
-		bool GetSupportsWeb() const;
+        bool GetSupportsPlatform(const String& platform) const;
+        bool GetSupportsDesktop() const;
+        bool GetSupportsAndroid() const;
+        bool GetSupportsIOS() const;
+        bool GetSupportsWeb() const;
 
-		void AddSupportedPlatform(const String& platform);
+        void AddSupportedPlatform(const String& platform);
 
-	private:
+    private:
 
-		void SetDefault();
+        void SetDefault();
 
-		String name_;
-		List<String> platforms_;
+        String name_;
+        List<String> platforms_;
 
-		SharedPtr<DesktopProjectSettings> desktopSettings_;
-		SharedPtr<AndroidProjectSettings> androidSettings_;
+        SharedPtr<DesktopProjectSettings> desktopSettings_;
+        SharedPtr<AndroidProjectSettings> androidSettings_;
 
-	};
+    };
 
 }

+ 1 - 1
Source/ToolCore/ToolEnvironment.cpp

@@ -55,7 +55,7 @@ bool ToolEnvironment::InitFromPackage()
     FileSystem* fileSystem = GetSubsystem<FileSystem>();
 
 #ifdef ATOMIC_PLATFORM_WINDOWS
-	editorBinary_ = fileSystem->GetProgramDir() + "AtomicEditor.exe";
+    editorBinary_ = fileSystem->GetProgramDir() + "AtomicEditor.exe";
     String resourcesDir = fileSystem->GetProgramDir() + "Resources/";
 #elif ATOMIC_PLATFORM_LINUX
     editorBinary_ = fileSystem->GetProgramDir() + "AtomicEditor";