소스 검색

Attempted merge of Leap motion and current development. Windows support first.

MichPerry-GG 11 년 전
부모
커밋
f2c757fbd6
87개의 변경된 파일9950개의 추가작업 그리고 323개의 파일을 삭제
  1. BIN
      Leap.dll
  2. BIN
      Leapd.dll
  3. 16 9
      engine/compilers/VisualStudio 2010/Torque 2D.vcxproj
  4. 24 0
      engine/compilers/VisualStudio 2010/Torque 2D.vcxproj.filters
  5. 16 9
      engine/compilers/VisualStudio 2012/Torque 2D.vcxproj
  6. 24 0
      engine/compilers/VisualStudio 2012/Torque 2D.vcxproj.filters
  7. 4566 0
      engine/lib/LeapSDK/include/Leap.h
  8. 1036 0
      engine/lib/LeapSDK/include/LeapMath.h
  9. BIN
      engine/lib/LeapSDK/lib/libLeap.dylib
  10. BIN
      engine/lib/LeapSDK/lib/libc++/libLeap.dylib
  11. BIN
      engine/lib/LeapSDK/lib/x64/Leap.dll
  12. BIN
      engine/lib/LeapSDK/lib/x64/Leapd.dll
  13. BIN
      engine/lib/LeapSDK/lib/x64/msvcp100.dll
  14. BIN
      engine/lib/LeapSDK/lib/x64/msvcp100d.dll
  15. BIN
      engine/lib/LeapSDK/lib/x64/msvcr100.dll
  16. BIN
      engine/lib/LeapSDK/lib/x64/msvcr100d.dll
  17. BIN
      engine/lib/LeapSDK/lib/x86/Leap.dll
  18. BIN
      engine/lib/LeapSDK/lib/x86/Leap.lib
  19. BIN
      engine/lib/LeapSDK/lib/x86/Leapd.dll
  20. BIN
      engine/lib/LeapSDK/lib/x86/Leapd.lib
  21. BIN
      engine/lib/LeapSDK/lib/x86/msvcp100.dll
  22. BIN
      engine/lib/LeapSDK/lib/x86/msvcp100d.dll
  23. BIN
      engine/lib/LeapSDK/lib/x86/msvcr100.dll
  24. BIN
      engine/lib/LeapSDK/lib/x86/msvcr100d.dll
  25. 7 7
      engine/source/gui/guiCanvas.cc
  26. 536 255
      engine/source/input/actionMap.cc
  27. 9 2
      engine/source/input/actionMap.h
  28. 176 0
      engine/source/input/leapMotion/LeapMotionManager_ScriptBinding.h
  29. 35 0
      engine/source/input/leapMotion/leapMotionConstants.h
  30. 674 0
      engine/source/input/leapMotion/leapMotionManager.cc
  31. 162 0
      engine/source/input/leapMotion/leapMotionManager.h
  32. 109 0
      engine/source/input/leapMotion/leapMotionUtil.cpp
  33. 48 0
      engine/source/input/leapMotion/leapMotionUtil.h
  34. 13 0
      engine/source/math/mMatrix.h
  35. 55 0
      engine/source/math/mPoint.cpp
  36. 45 0
      engine/source/math/mPoint.h
  37. 55 27
      engine/source/platform/event.h
  38. 8 8
      engine/source/platformWin32/winDInputDevice.cc
  39. 1 1
      engine/source/platformWin32/winDirectInput.cc
  40. 5 5
      engine/source/platformWin32/winWindow.cc
  41. 7 0
      modules/LeapToy/1/assets/animations/Digital_ExplosionAnimation.asset.taml
  42. 5 0
      modules/LeapToy/1/assets/animations/Projectile_Digital_StrikeAnimation.asset.taml
  43. 6 0
      modules/LeapToy/1/assets/animations/blockAnim.asset.taml
  44. 6 0
      modules/LeapToy/1/assets/animations/brickAnim.asset.taml
  45. 8 0
      modules/LeapToy/1/assets/images/Digital_Explosion.asset.taml
  46. BIN
      modules/LeapToy/1/assets/images/Digital_Explosion.png
  47. 8 0
      modules/LeapToy/1/assets/images/Projectile_Digital_Strike.asset.taml
  48. BIN
      modules/LeapToy/1/assets/images/Projectile_Digital_Strike.png
  49. 3 0
      modules/LeapToy/1/assets/images/barrierWall.asset.taml
  50. BIN
      modules/LeapToy/1/assets/images/barrierWall.png
  51. 3 0
      modules/LeapToy/1/assets/images/blockGlow.asset.taml
  52. BIN
      modules/LeapToy/1/assets/images/blockGlow.png
  53. 3 0
      modules/LeapToy/1/assets/images/circleThree.asset.taml
  54. BIN
      modules/LeapToy/1/assets/images/circleThree.png
  55. 3 0
      modules/LeapToy/1/assets/images/complexCircle.asset.taml
  56. BIN
      modules/LeapToy/1/assets/images/complexCircle.png
  57. 3 0
      modules/LeapToy/1/assets/images/menuBackground.asset.taml
  58. BIN
      modules/LeapToy/1/assets/images/menuBackground.jpg
  59. 9 0
      modules/LeapToy/1/assets/images/objectsBlocks.asset.taml
  60. BIN
      modules/LeapToy/1/assets/images/objectsBlocks.png
  61. 7 0
      modules/LeapToy/1/assets/images/objectsBricks.asset.taml
  62. BIN
      modules/LeapToy/1/assets/images/objectsBricks.png
  63. 3 0
      modules/LeapToy/1/assets/images/playerUfo.asset.taml
  64. BIN
      modules/LeapToy/1/assets/images/playerUfo.png
  65. 3 0
      modules/LeapToy/1/assets/images/simpleCircle.asset.taml
  66. BIN
      modules/LeapToy/1/assets/images/simpleCircle.png
  67. 3 0
      modules/LeapToy/1/assets/images/widgetBall.asset.taml
  68. BIN
      modules/LeapToy/1/assets/images/widgetBall.png
  69. 3 0
      modules/LeapToy/1/assets/images/widgetFruit.asset.taml
  70. BIN
      modules/LeapToy/1/assets/images/widgetFruit.png
  71. 3 0
      modules/LeapToy/1/assets/images/window.asset.taml
  72. BIN
      modules/LeapToy/1/assets/images/window.png
  73. 129 0
      modules/LeapToy/1/assets/particles/blockFadeParticle.asset.taml
  74. 69 0
      modules/LeapToy/1/assets/particles/digitalExplosion.asset.taml
  75. 79 0
      modules/LeapToy/1/assets/particles/digitalFire.asset.taml
  76. 180 0
      modules/LeapToy/1/main.cs
  77. 15 0
      modules/LeapToy/1/module.taml
  78. 80 0
      modules/LeapToy/1/scripts/DealsDamageBehavior.cs
  79. 59 0
      modules/LeapToy/1/scripts/SwapImageOnCollision.cs
  80. 133 0
      modules/LeapToy/1/scripts/TakesDamageBehavior.cs
  81. 198 0
      modules/LeapToy/1/scripts/breakoutDemo.cs
  82. 286 0
      modules/LeapToy/1/scripts/builderDemo.cs
  83. 112 0
      modules/LeapToy/1/scripts/fingerDemo.cs
  84. 376 0
      modules/LeapToy/1/scripts/gestureDemo.cs
  85. 88 0
      modules/LeapToy/1/scripts/helpText.cs
  86. 315 0
      modules/LeapToy/1/scripts/input.cs
  87. 125 0
      modules/LeapToy/1/scripts/toy.cs

BIN
Leap.dll


BIN
Leapd.dll


+ 16 - 9
engine/compilers/VisualStudio 2010/Torque 2D.vcxproj

@@ -72,7 +72,7 @@
     </Midl>
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>../../Lib/zlib;../../Lib/lpng;../../Lib/ljpeg;../../Lib/openal/win32;../../Source;../../Source/persistence/rapidjson/include;../../source/testing/googleTest;../../source/testing/googleTest/include;../../source/testing/googleTest;../../source/testing/googleTest/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>../../Lib/LeapSDK/include;../../Lib/zlib;../../Lib/lpng;../../Lib/ljpeg;../../Lib/openal/win32;../../Source;../../Source/persistence/rapidjson/include;../../source/testing/googleTest;../../source/testing/googleTest/include;../../source/testing/googleTest;../../source/testing/googleTest/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>TORQUE_DEBUG;TORQUE_DEBUG_GUARD;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@@ -96,10 +96,10 @@
       <AdditionalIncludeDirectories>../../Lib/MSPlatformSDK/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ResourceCompile>
     <Link>
-      <AdditionalDependencies>COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;RPCRT4.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;unicows.lib;shell32.lib;shlwapi.lib;ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>Leapd.lib;COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;RPCRT4.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;unicows.lib;shell32.lib;shlwapi.lib;ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>../../../Torque2D_DEBUG.exe</OutputFile>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <AdditionalLibraryDirectories>../../Lib/unicode;../../lib/MSPlatformSDK/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>../../lib/LeapSDK/lib/x86;../../Lib/unicode;../../lib/MSPlatformSDK/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <IgnoreSpecificDefaultLibraries>LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <ProgramDatabaseFile>$(IntDir)$(ProjectName).pdb</ProgramDatabaseFile>
@@ -119,7 +119,7 @@
     <ClCompile>
       <Optimization>MinSpace</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>../../Lib/zlib;../../Lib/lpng;../../Lib/ljpeg;../../Lib/openal/win32;../../Source;../../Source/persistence/rapidjson/include;../../source/testing/googleTest;../../source/testing/googleTest/include;../../source/testing/googleTest;../../source/testing/googleTest/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>../../Lib/LeapSDK/include;../../Lib/zlib;../../Lib/lpng;../../Lib/ljpeg;../../Lib/openal/win32;../../Source;../../Source/persistence/rapidjson/include;../../source/testing/googleTest;../../source/testing/googleTest/include;../../source/testing/googleTest;../../source/testing/googleTest/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@@ -144,10 +144,10 @@
       <AdditionalIncludeDirectories>../../Lib/MSPlatformSDK/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ResourceCompile>
     <Link>
-      <AdditionalDependencies>COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;unicows.lib;shell32.lib;shlwapi.lib;ole32.lib;RPCRT4.LIB;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>Leap.lib;COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;unicows.lib;shell32.lib;shlwapi.lib;ole32.lib;RPCRT4.LIB;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>../../../Torque2D.exe</OutputFile>
       <SuppressStartupBanner>false</SuppressStartupBanner>
-      <AdditionalLibraryDirectories>../../Lib/unicode;../../Lib/MSPlatformSDK/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>../../lib/LeapSDK/lib/x86;../../Lib/unicode;../../Lib/MSPlatformSDK/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <IgnoreSpecificDefaultLibraries>LIBC;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
       <GenerateDebugInformation>false</GenerateDebugInformation>
       <ProgramDatabaseFile>$(IntDir)$(ProjectName).pdb</ProgramDatabaseFile>
@@ -178,7 +178,7 @@
     <ClCompile>
       <Optimization>MinSpace</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>../../Lib/zlib;../../Lib/lpng;../../Lib/ljpeg;../../Lib/openal/win32;../../Source;../../Source/persistence/rapidjson/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>../../Lib/LeapSDK/include;../../Lib/zlib;../../Lib/lpng;../../Lib/ljpeg;../../Lib/openal/win32;../../Source;../../Source/persistence/rapidjson/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>TORQUE_SHIPPING;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@@ -203,10 +203,10 @@
       <AdditionalIncludeDirectories>../../Lib/MSPlatformSDK/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ResourceCompile>
     <Link>
-      <AdditionalDependencies>COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;unicows.lib;shell32.lib;shlwapi.lib;ole32.lib;RPCRT4.LIB;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>Leap.lib;COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;unicows.lib;shell32.lib;shlwapi.lib;ole32.lib;RPCRT4.LIB;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>../../../Torque2D.exe</OutputFile>
       <SuppressStartupBanner>false</SuppressStartupBanner>
-      <AdditionalLibraryDirectories>../../Lib/unicode;../../Lib/MSPlatformSDK/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>../../lib/LeapSDK/lib/x86;../../Lib/unicode;../../Lib/MSPlatformSDK/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <IgnoreSpecificDefaultLibraries>LIBC;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
       <GenerateDebugInformation>false</GenerateDebugInformation>
       <ProgramDatabaseFile>$(IntDir)$(ProjectName).pdb</ProgramDatabaseFile>
@@ -404,6 +404,8 @@
     <ClCompile Include="..\..\source\gui\language\lang.cc" />
     <ClCompile Include="..\..\source\gui\messageVector.cc" />
     <ClCompile Include="..\..\source\input\actionMap.cc" />
+    <ClCompile Include="..\..\source\input\leapMotion\leapMotionManager.cc" />
+    <ClCompile Include="..\..\source\input\leapMotion\leapMotionUtil.cpp" />
     <ClCompile Include="..\..\source\io\bitStream.cc" />
     <ClCompile Include="..\..\source\io\bufferStream.cc" />
     <ClCompile Include="..\..\source\io\fileObject.cc" />
@@ -429,6 +431,7 @@
     <ClCompile Include="..\..\source\io\zip\zipSubStream.cc" />
     <ClCompile Include="..\..\source\io\zip\zipTempStream.cc" />
     <ClCompile Include="..\..\source\math\math_ScriptBinding.cc" />
+    <ClCompile Include="..\..\source\math\mPoint.cpp" />
     <ClCompile Include="..\..\source\math\rectClipper.cpp" />
     <ClCompile Include="..\..\source\memory\dataChunker.cc" />
     <ClCompile Include="..\..\source\memory\frameAllocator_ScriptBinding.cc" />
@@ -878,6 +881,10 @@
     <ClInclude Include="..\..\source\gui\messageVector.h" />
     <ClInclude Include="..\..\source\input\actionMap.h" />
     <ClInclude Include="..\..\source\input\actionMap_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\input\leapMotion\leapMotionConstants.h" />
+    <ClInclude Include="..\..\source\input\leapMotion\leapMotionManager.h" />
+    <ClInclude Include="..\..\source\input\leapMotion\LeapMotionManager_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\input\leapMotion\leapMotionUtil.h" />
     <ClInclude Include="..\..\source\io\bitStream.h" />
     <ClInclude Include="..\..\source\io\bufferStream.h" />
     <ClInclude Include="..\..\source\io\fileObject.h" />

+ 24 - 0
engine/compilers/VisualStudio 2010/Torque 2D.vcxproj.filters

@@ -193,6 +193,9 @@
     <Filter Include="persistence\taml\xml">
       <UniqueIdentifier>{e8f11d4b-6a54-4467-ae13-794ed56063f9}</UniqueIdentifier>
     </Filter>
+    <Filter Include="input\leapMotion">
+      <UniqueIdentifier>{aa5d5692-e20a-4608-b3ee-390b3089fcb2}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\source\audio\audio.cc">
@@ -1338,6 +1341,15 @@
     <ClCompile Include="..\..\source\console\Package.cc">
       <Filter>console</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\source\input\leapMotion\leapMotionManager.cc">
+      <Filter>input\leapMotion</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\input\leapMotion\leapMotionUtil.cpp">
+      <Filter>input\leapMotion</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\math\mPoint.cpp">
+      <Filter>math</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -2979,6 +2991,18 @@
     <ClInclude Include="..\..\source\console\Package.h">
       <Filter>console</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\input\leapMotion\leapMotionConstants.h">
+      <Filter>input\leapMotion</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\input\leapMotion\leapMotionManager.h">
+      <Filter>input\leapMotion</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\input\leapMotion\LeapMotionManager_ScriptBinding.h">
+      <Filter>input\leapMotion</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\input\leapMotion\leapMotionUtil.h">
+      <Filter>input\leapMotion</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 16 - 9
engine/compilers/VisualStudio 2012/Torque 2D.vcxproj

@@ -75,7 +75,7 @@
     </Midl>
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>../../Lib/zlib;../../Lib/lpng;../../Lib/ljpeg;../../Lib/openal/win32;../../Source;../../Source/persistence/rapidjson/include;../../Source/persistence/libjson;../../source/testing/googleTest;../../source/testing/googleTest/include;../../source/testing/googleTest;../../source/testing/googleTest/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>../../Lib/LeapSDK/include;../../Lib/zlib;../../Lib/lpng;../../Lib/ljpeg;../../Lib/openal/win32;../../Source;../../Source/persistence/rapidjson/include;../../Source/persistence/libjson;../../source/testing/googleTest;../../source/testing/googleTest/include;../../source/testing/googleTest;../../source/testing/googleTest/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>TORQUE_DEBUG;TORQUE_DEBUG_GUARD;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@@ -100,10 +100,10 @@
       <AdditionalIncludeDirectories>../../Lib/MSPlatformSDK/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ResourceCompile>
     <Link>
-      <AdditionalDependencies>COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;RPCRT4.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;unicows.lib;shell32.lib;shlwapi.lib;ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>Leapd.lib;COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;RPCRT4.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;unicows.lib;shell32.lib;shlwapi.lib;ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>../../../Torque2D_DEBUG.exe</OutputFile>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <AdditionalLibraryDirectories>../../Lib/unicode;../../lib/MSPlatformSDK/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>../../lib/LeapSDK/lib/x86;../../Lib/unicode;../../lib/MSPlatformSDK/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <IgnoreSpecificDefaultLibraries>LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <ProgramDatabaseFile>$(IntDir)$(ProjectName).pdb</ProgramDatabaseFile>
@@ -124,7 +124,7 @@
     <ClCompile>
       <Optimization>MinSpace</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>../../Lib/zlib;../../Lib/lpng;../../Lib/ljpeg;../../Lib/openal/win32;../../Source;../../Source/persistence/rapidjson/include;../../Source/persistence/libjson;../../source/testing/googleTest;../../source/testing/googleTest/include;../../source/testing/googleTest;../../source/testing/googleTest/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>../../Lib/LeapSDK/include;../../Lib/zlib;../../Lib/lpng;../../Lib/ljpeg;../../Lib/openal/win32;../../Source;../../Source/persistence/rapidjson/include;../../Source/persistence/libjson;../../source/testing/googleTest;../../source/testing/googleTest/include;../../source/testing/googleTest;../../source/testing/googleTest/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@@ -149,10 +149,10 @@
       <AdditionalIncludeDirectories>../../Lib/MSPlatformSDK/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ResourceCompile>
     <Link>
-      <AdditionalDependencies>COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;unicows.lib;shell32.lib;shlwapi.lib;ole32.lib;RPCRT4.LIB;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>Leap.lib;COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;unicows.lib;shell32.lib;shlwapi.lib;ole32.lib;RPCRT4.LIB;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>../../../Torque2D.exe</OutputFile>
       <SuppressStartupBanner>false</SuppressStartupBanner>
-      <AdditionalLibraryDirectories>../../Lib/unicode;../../Lib/MSPlatformSDK/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>../../lib/LeapSDK/lib/x86;../../Lib/unicode;../../Lib/MSPlatformSDK/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <IgnoreSpecificDefaultLibraries>LIBC;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
       <GenerateDebugInformation>false</GenerateDebugInformation>
       <ProgramDatabaseFile>$(IntDir)$(ProjectName).pdb</ProgramDatabaseFile>
@@ -184,7 +184,7 @@
     <ClCompile>
       <Optimization>MinSpace</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>../../Lib/zlib;../../Lib/lpng;../../Lib/ljpeg;../../Lib/openal/win32;../../Source;../../Source/persistence/rapidjson/include;../../Source/persistence/libjson;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>../../Lib/LeapSDK/include;../../Lib/zlib;../../Lib/lpng;../../Lib/ljpeg;../../Lib/openal/win32;../../Source;../../Source/persistence/rapidjson/include;../../Source/persistence/libjson;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>TORQUE_SHIPPING;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@@ -209,10 +209,10 @@
       <AdditionalIncludeDirectories>../../Lib/MSPlatformSDK/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ResourceCompile>
     <Link>
-      <AdditionalDependencies>COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;unicows.lib;shell32.lib;shlwapi.lib;ole32.lib;RPCRT4.LIB;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>Leap.lib;COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;unicows.lib;shell32.lib;shlwapi.lib;ole32.lib;RPCRT4.LIB;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>../../../Torque2D.exe</OutputFile>
       <SuppressStartupBanner>false</SuppressStartupBanner>
-      <AdditionalLibraryDirectories>../../Lib/unicode;../../Lib/MSPlatformSDK/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>../../lib/LeapSDK/lib/x86;../../Lib/unicode;../../Lib/MSPlatformSDK/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <IgnoreSpecificDefaultLibraries>LIBC;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
       <GenerateDebugInformation>false</GenerateDebugInformation>
       <ProgramDatabaseFile>$(IntDir)$(ProjectName).pdb</ProgramDatabaseFile>
@@ -411,6 +411,8 @@
     <ClCompile Include="..\..\source\gui\language\lang.cc" />
     <ClCompile Include="..\..\source\gui\messageVector.cc" />
     <ClCompile Include="..\..\source\input\actionMap.cc" />
+    <ClCompile Include="..\..\source\input\leapMotion\leapMotionManager.cc" />
+    <ClCompile Include="..\..\source\input\leapMotion\leapMotionUtil.cpp" />
     <ClCompile Include="..\..\source\io\bitStream.cc" />
     <ClCompile Include="..\..\source\io\bufferStream.cc" />
     <ClCompile Include="..\..\source\io\fileObject.cc" />
@@ -436,6 +438,7 @@
     <ClCompile Include="..\..\source\io\zip\zipSubStream.cc" />
     <ClCompile Include="..\..\source\io\zip\zipTempStream.cc" />
     <ClCompile Include="..\..\source\math\math_ScriptBinding.cc" />
+    <ClCompile Include="..\..\source\math\mPoint.cpp" />
     <ClCompile Include="..\..\source\math\rectClipper.cpp" />
     <ClCompile Include="..\..\source\memory\dataChunker.cc" />
     <ClCompile Include="..\..\source\memory\frameAllocator_ScriptBinding.cc" />
@@ -885,6 +888,10 @@
     <ClInclude Include="..\..\source\gui\messageVector.h" />
     <ClInclude Include="..\..\source\input\actionMap.h" />
     <ClInclude Include="..\..\source\input\actionMap_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\input\leapMotion\leapMotionConstants.h" />
+    <ClInclude Include="..\..\source\input\leapMotion\leapMotionManager.h" />
+    <ClInclude Include="..\..\source\input\leapMotion\LeapMotionManager_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\input\leapMotion\leapMotionUtil.h" />
     <ClInclude Include="..\..\source\io\bitStream.h" />
     <ClInclude Include="..\..\source\io\bufferStream.h" />
     <ClInclude Include="..\..\source\io\fileObject.h" />

+ 24 - 0
engine/compilers/VisualStudio 2012/Torque 2D.vcxproj.filters

@@ -193,6 +193,9 @@
     <Filter Include="persistence\taml\xml">
       <UniqueIdentifier>{cc1c1416-376b-4686-a4ac-21d1a35c9390}</UniqueIdentifier>
     </Filter>
+    <Filter Include="input\leapMotion">
+      <UniqueIdentifier>{addcb993-5059-42bf-a1ea-871f700c67c3}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\source\audio\audio.cc">
@@ -1338,6 +1341,15 @@
     <ClCompile Include="..\..\source\console\Package.cc">
       <Filter>console</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\source\input\leapMotion\leapMotionManager.cc">
+      <Filter>input\leapMotion</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\input\leapMotion\leapMotionUtil.cpp">
+      <Filter>input\leapMotion</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\math\mPoint.cpp">
+      <Filter>math</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -2979,6 +2991,18 @@
     <ClInclude Include="..\..\source\console\Package.h">
       <Filter>console</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\input\leapMotion\leapMotionConstants.h">
+      <Filter>input\leapMotion</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\input\leapMotion\leapMotionManager.h">
+      <Filter>input\leapMotion</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\input\leapMotion\LeapMotionManager_ScriptBinding.h">
+      <Filter>input\leapMotion</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\input\leapMotion\leapMotionUtil.h">
+      <Filter>input\leapMotion</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 4566 - 0
engine/lib/LeapSDK/include/Leap.h

@@ -0,0 +1,4566 @@
+/******************************************************************************\
+* Copyright (C) 2012-2013 Leap Motion, Inc. All rights reserved.               *
+* Leap Motion proprietary and confidential. Not for distribution.              *
+* Use subject to the terms of the Leap Motion SDK Agreement available at       *
+* https://developer.leapmotion.com/sdk_agreement, or another agreement         *
+* between Leap Motion and you, your company or other organization.             *
+\******************************************************************************/
+
+#if !defined(__Leap_h__)
+#define __Leap_h__
+
+#include "LeapMath.h"
+#include <string>
+#include <vector>
+
+// Define integer types for Visual Studio 2008 and earlier
+#if defined(_MSC_VER) && (_MSC_VER < 1600)
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#else
+#include <stdint.h>
+#endif
+
+// Define Leap export macros
+#if defined(_WIN32) // Windows
+#if LEAP_API_INTERNAL
+#define LEAP_EXPORT
+#elif LEAP_API_IMPLEMENTATION
+#define LEAP_EXPORT __declspec(dllexport)
+#else
+#define LEAP_EXPORT __declspec(dllimport)
+#endif
+#define LEAP_EXPORT_CLASS
+#define LEAP_EXPORT_PLUGIN __declspec(dllexport)
+#elif !defined(SWIG)
+#define LEAP_EXPORT __attribute__((visibility("default")))
+#define LEAP_EXPORT_CLASS __attribute__((visibility("default")))
+#define LEAP_EXPORT_PLUGIN __attribute__((visibility("default")))
+#else
+#define LEAP_EXPORT
+#define LEAP_EXPORT_CLASS
+#define LEAP_EXPORT_PLUGIN
+#endif
+
+namespace Leap {
+
+  // Interface for internal use only
+  class LEAP_EXPORT_CLASS Interface {
+  public:
+    struct Implementation {
+      LEAP_EXPORT virtual ~Implementation() {}
+    };
+  protected:
+    LEAP_EXPORT Interface(void* owner);
+    LEAP_EXPORT Interface(Implementation* reference, void* owner);
+    LEAP_EXPORT Interface(const Interface& rhs);
+    Interface(class SharedObject* object);
+    LEAP_EXPORT Interface& operator=(const Interface& rhs);
+    LEAP_EXPORT virtual ~Interface();
+    template<typename T> T* get() const { return static_cast<T*>(reference()); }
+    class SharedObject* m_object;
+  private:
+    LEAP_EXPORT Implementation* reference() const;
+  };
+
+  // Forward declarations for internal use only
+  class PointableImplementation;
+  class FingerImplementation;
+  class ToolImplementation;
+  class HandImplementation;
+  class GestureImplementation;
+  class ScreenImplementation;
+  class DeviceImplementation;
+  class InteractionBoxImplementation;
+  class FrameImplementation;
+  class ControllerImplementation;
+  template<typename T> class ListBaseImplementation;
+
+  // Forward declarations
+  class PointableList;
+  class FingerList;
+  class ToolList;
+  class HandList;
+  class GestureList;
+  class Hand;
+  class Gesture;
+  class Screen;
+  class InteractionBox;
+  class Frame;
+  class Listener;
+
+  /**
+   * The Pointable class reports the physical characteristics of a detected finger or tool.
+   *
+   * Both fingers and tools are classified as Pointable objects. Use the Pointable::isFinger()
+   * function to determine whether a Pointable object represents a finger. Use the
+   * Pointable::isTool() function to determine whether a Pointable object represents a tool.
+   * The Leap Motion software classifies a detected entity as a tool when it is thinner, straighter, and longer
+   * than a typical finger.
+   *
+   * \include Pointable_Get_Basic.txt
+   *
+   * To provide touch emulation, the Leap Motion software associates a floating touch
+   * plane that adapts to the user's finger movement and hand posture. The Leap Motion
+   * interprets purposeful movements toward this plane as potential touch points.
+   * The Pointable class reports
+   * touch state with the touchZone and touchDistance values.
+   *
+   * Note that Pointable objects can be invalid, which means that they do not contain
+   * valid tracking data and do not correspond to a physical entity. Invalid Pointable
+   * objects can be the result of asking for a Pointable object using an ID from an
+   * earlier frame when no Pointable objects with that ID exist in the current frame.
+   * A Pointable object created from the Pointable constructor is also invalid.
+   * Test for validity with the Pointable::isValid() function.
+   *
+   * @since 1.0
+   */
+  class Pointable : public Interface {
+  public:
+
+    /**
+     * Defines the values for reporting the state of a Pointable object in relation to
+     * an adaptive touch plane.
+     * @since 1.0
+     */
+    enum Zone {
+      /**
+       * The Pointable object is too far from the plane to be
+       * considered hovering or touching.
+       * @since 1.0
+       */
+      ZONE_NONE       = 0,
+      /**
+       * The Pointable object is close to, but not touching
+       * the plane.
+       * @since 1.0
+       */
+      ZONE_HOVERING   = 1,
+      /**
+       * The Pointable has penetrated the plane.
+       * @since 1.0
+       */
+      ZONE_TOUCHING   = 2,
+    };
+
+    // For internal use only.
+    Pointable(PointableImplementation*);
+    // For internal use only.
+    Pointable(FingerImplementation*);
+    // For internal use only.
+    Pointable(ToolImplementation*);
+
+    /**
+     * Constructs a Pointable object.
+     *
+     * An uninitialized pointable is considered invalid.
+     * Get valid Pointable objects from a Frame or a Hand object.
+     *
+     * \include Pointable_Pointable.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT Pointable();
+
+    /**
+     * A unique ID assigned to this Pointable object, whose value remains the
+     * same across consecutive frames while the tracked finger or tool remains
+     * visible. If tracking is lost (for example, when a finger is occluded by
+     * another finger or when it is withdrawn from the Leap Motion Controller field of view), the
+     * Leap Motion software may assign a new ID when it detects the entity in a future frame.
+     *
+     * \include Pointable_id.txt
+     *
+     * Use the ID value with the Frame::pointable() function to find this
+     * Pointable object in future frames.
+     *
+     * IDs should be from 1 to 100 (inclusive). If more than 100 objects are tracked
+     * an IDs of -1 will be used until an ID in the defined range is available.
+     *
+     * @returns The ID assigned to this Pointable object.
+     * @since 1.0
+     */
+    LEAP_EXPORT int32_t id() const;
+
+    /**
+     * The Frame associated with this Pointable object.
+     *
+     * \include Pointable_frame.txt
+     *
+     * @returns The associated Frame object, if available; otherwise,
+     * an invalid Frame object is returned.
+     * @since 1.0
+     */
+    LEAP_EXPORT Frame frame() const;
+
+    /**
+     * The Hand associated with this finger or tool.
+     *
+     * \include Pointable_hand.txt
+     *
+     * @returns The associated Hand object, if available; otherwise,
+     * an invalid Hand object is returned.
+     * @since 1.0
+     */
+    LEAP_EXPORT Hand hand() const;
+
+    /**
+     * The tip position in millimeters from the Leap Motion origin.
+     *
+     * \include Pointable_tipPosition.txt
+     *
+     * @returns The Vector containing the coordinates of the tip position.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector tipPosition() const;
+
+    /**
+     * The rate of change of the tip position in millimeters/second.
+     *
+     * \include Pointable_tipVelocity.txt
+     *
+     * @returns The Vector containing the coordinates of the tip velocity.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector tipVelocity() const;
+
+    /**
+     * The direction in which this finger or tool is pointing.
+     *
+     * \include Pointable_direction.txt
+     *
+     * The direction is expressed as a unit vector pointing in the same
+     * direction as the tip.
+     *
+     * \image html images/Leap_Finger_Model.png
+     *
+     * @returns The Vector pointing in the same direction as the tip of this
+     * Pointable object.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector direction() const;
+
+    /**
+     * The estimated width of the finger or tool in millimeters.
+     *
+     * \include Pointable_width.txt
+     *
+     * The reported width is the average width of the visible portion of the
+     * finger or tool from the hand to the tip. If the width isn't known,
+     * then a value of 0 is returned.
+     *
+     * @returns The estimated width of this Pointable object.
+     * @since 1.0
+     */
+    LEAP_EXPORT float width() const;
+
+    /**
+     * The estimated length of the finger or tool in millimeters.
+     *
+     * The reported length is the visible length of the finger or tool from the
+     * hand to tip. If the length isn't known, then a value of 0 is returned.
+     *
+     * \include Pointable_length.txt
+     *
+     * @returns The estimated length of this Pointable object.
+     * @since 1.0
+     */
+    LEAP_EXPORT float length() const;
+
+    /**
+     * Whether or not the Pointable is believed to be a finger.
+     * Fingers are generally shorter, thicker, and less straight than tools.
+     *
+     * \include Pointable_Conversion.txt
+     *
+     * @returns True, if this Pointable is classified as a finger.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isFinger() const;
+
+    /**
+     * Whether or not the Pointable is believed to be a tool.
+     * Tools are generally longer, thinner, and straighter than fingers.
+     *
+     * \include Pointable_Conversion.txt
+     *
+     * @returns True, if this Pointable is classified as a tool.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isTool() const;
+
+    /**
+     * Reports whether this is a valid Pointable object.
+     *
+     * \include Pointable_isValid.txt
+     *
+     * @returns True, if this Pointable object contains valid tracking data.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isValid() const;
+
+    /**
+     * The current touch zone of this Pointable object.
+     *
+     * The Leap Motion software computes the touch zone based on a floating touch
+     * plane that adapts to the user's finger movement and hand posture. The Leap
+     * Motion software interprets purposeful movements toward this plane as potential touch
+     * points. When a Pointable moves close to the adaptive touch plane, it enters the
+     * "hovering" zone. When a Pointable reaches or passes through the plane, it enters
+     * the "touching" zone.
+     *
+     * The possible states are present in the Zone enum of this class:
+     *
+     * * Zone.NONE -- The Pointable is outside the hovering zone.
+     * * Zone.HOVERING -- The Pointable is close to, but not touching the touch plane.
+     * * Zone.TOUCHING -- The Pointable has penetrated the touch plane.
+     *
+     * The touchDistance value provides a normalized indication of the distance to
+     * the touch plane when the Pointable is in the hovering or touching zones.
+     *
+     * \include Pointable_touchZone.txt
+     *
+     * @returns The touch zone of this Pointable
+     * @since 1.0
+     */
+    LEAP_EXPORT Zone touchZone() const;
+
+    /**
+     * A value proportional to the distance between this Pointable object and the
+     * adaptive touch plane.
+     *
+     * \image html images/Leap_Touch_Plane.png
+     *
+     * The touch distance is a value in the range [-1, 1]. The value 1.0 indicates the
+     * Pointable is at the far edge of the hovering zone. The value 0 indicates the
+     * Pointable is just entering the touching zone. A value of -1.0 indicates the
+     * Pointable is firmly within the touching zone. Values in between are
+     * proportional to the distance from the plane. Thus, the touchDistance of 0.5
+     * indicates that the Pointable is halfway into the hovering zone.
+     *
+     * \include Pointable_touchDistance.txt
+     *
+     * You can use the touchDistance value to modulate visual feedback given to the
+     * user as their fingers close in on a touch target, such as a button.
+     *
+     * @returns The normalized touch distance of this Pointable object.
+     * @since 1.0
+     */
+    LEAP_EXPORT float touchDistance() const;
+
+    /**
+     * The stabilized tip position of this Pointable.
+     *
+     * Smoothing and stabilization is performed in order to make
+     * this value more suitable for interaction with 2D content. The stabilized
+     * position lags behind the tip position by a variable amount, depending
+     * primarily on the speed of movement.
+     *
+     * \include Pointable_stabilizedTipPosition.txt
+     *
+     * @returns A modified tip position of this Pointable object
+     * with some additional smoothing and stabilization applied.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector stabilizedTipPosition() const;
+
+    /**
+     * The duration of time this Pointable has been visible to the Leap Motion Controller.
+     *
+     * \include Pointable_timeVisible.txt
+     *
+     * @returns The duration (in seconds) that this Pointable has been tracked.
+     * @since 1.0
+     */
+    LEAP_EXPORT float timeVisible() const;
+
+    /**
+     * Returns an invalid Pointable object.
+     *
+     * You can use the instance returned by this function in comparisons testing
+     * whether a given Pointable instance is valid or invalid. (You can also use the
+     * Pointable::isValid() function.)
+     *
+     * \include Pointable_invalid.txt
+     *
+     * @returns The invalid Pointable instance.
+     * @since 1.0
+     */
+    LEAP_EXPORT static const Pointable& invalid();
+
+    /**
+     * Compare Pointable object equality.
+     *
+     * \include Pointable_operator_equals.txt
+     *
+     * Two Pointable objects are equal if and only if both Pointable objects represent the
+     * exact same physical entities in the same frame and both Pointable objects are valid.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator==(const Pointable&) const;
+
+    /**
+     * Compare Pointable object inequality.
+     *
+     * \include Pointable_operator_not_equal.txt
+     *
+     * Two Pointable objects are equal if and only if both Pointable objects represent the
+     * exact same physical entities in the same frame and both Pointable objects are valid.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator!=(const Pointable&) const;
+
+    /**
+     * Writes a brief, human readable description of the Pointable object to an output stream.
+     *
+     * \include Pointable_operator_stream.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT friend std::ostream& operator<<(std::ostream&, const Pointable&);
+
+    /**
+     * A string containing a brief, human readable description of the Pointable object.
+     *
+     * @returns A description of the Pointable object as a string.
+     * @since 1.0
+     */
+    LEAP_EXPORT std::string toString() const;
+  };
+
+  /**
+   * The Finger class represents a tracked finger.
+   *
+   * Fingers are Pointable objects that the Leap Motion software has classified as a finger.
+   * Get valid Finger objects from a Frame or a Hand object.
+   *
+   * Fingers may be permanently associated to a hand. In this case the angular order of the finger IDs
+   * will be invariant. As fingers move in and out of view it is possible for the guessed ID
+   * of a finger to be incorrect. Consequently, it may be necessary for finger IDs to be
+   * exchanged. All tracked properties, such as velocity, will remain continuous in the API.
+   * However, quantities that are derived from the API output (such as a history of positions)
+   * will be discontinuous unless they have a corresponding ID exchange.
+   *
+   * Note that Finger objects can be invalid, which means that they do not contain
+   * valid tracking data and do not correspond to a physical finger. Invalid Finger
+   * objects can be the result of asking for a Finger object using an ID from an
+   * earlier frame when no Finger objects with that ID exist in the current frame.
+   * A Finger object created from the Finger constructor is also invalid.
+   * Test for validity with the Finger::isValid() function.
+   * @since 1.0
+   */
+  class Finger : public Pointable {
+  public:
+    // For internal use only.
+    Finger(FingerImplementation*);
+
+    /**
+     * Constructs a Finger object.
+     *
+     * An uninitialized finger is considered invalid.
+     * Get valid Finger objects from a Frame or a Hand object.
+     * @since 1.0
+     */
+    LEAP_EXPORT Finger();
+
+    /**
+     * If the specified Pointable object represents a finger, creates a copy
+     * of it as a Finger object; otherwise, creates an invalid Finger object.
+     *
+     * \include Finger_Finger.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT explicit Finger(const Pointable&);
+
+    /**
+     * Returns an invalid Finger object.
+     *
+     * You can use the instance returned by this function in comparisons testing
+     * whether a given Finger instance is valid or invalid. (You can also use the
+     * Finger::isValid() function.)
+     *
+     * \include Finger_invalid.txt
+     *
+     * @returns The invalid Finger instance.
+     * @since 1.0
+     */
+    LEAP_EXPORT static const Finger& invalid();
+
+    /**
+     * A string containing a brief, human readable description of the Finger object.
+     *
+     * @returns A description of the Finger object as a string.
+     * @since 1.0
+     */
+    LEAP_EXPORT std::string toString() const;
+  };
+
+  /**
+   * The Tool class represents a tracked tool.
+   *
+   * Tools are Pointable objects that the Leap Motion software has classified as a tool.
+   * Tools are longer, thinner, and straighter than a typical finger.
+   * Get valid Tool objects from a Frame or a Hand object.
+   *
+   * Tools may reference a hand, but unlike fingers they are not permanently associated.
+   * Instead, a tool can be transferred between hands while keeping the same ID.
+   *
+   * \image html images/Leap_Tool.png
+   *
+   * Note that Tool objects can be invalid, which means that they do not contain
+   * valid tracking data and do not correspond to a physical tool. Invalid Tool
+   * objects can be the result of asking for a Tool object using an ID from an
+   * earlier frame when no Tool objects with that ID exist in the current frame.
+   * A Tool object created from the Tool constructor is also invalid.
+   * Test for validity with the Tool::isValid() function.
+   * @since 1.0
+   */
+  class Tool : public Pointable {
+  public:
+    // For internal use only.
+    Tool(ToolImplementation*);
+
+    /**
+     * Constructs a Tool object.
+     *
+     * An uninitialized tool is considered invalid.
+     * Get valid Tool objects from a Frame or a Hand object.
+     *
+     * \include Tool_Tool.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT Tool();
+
+    /**
+     * If the specified Pointable object represents a tool, creates a copy
+     * of it as a Tool object; otherwise, creates an invalid Tool object.
+     *
+     * \include Tool_Tool_copy.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT explicit Tool(const Pointable&);
+
+    /**
+     * Returns an invalid Tool object.
+     *
+     * You can use the instance returned by this function in comparisons testing
+     * whether a given Tool instance is valid or invalid. (You can also use the
+     * Tool::isValid() function.)
+     *
+     * \include Tool_invalid.txt
+     *
+     * @returns The invalid Tool instance.
+     * @since 1.0
+     */
+    LEAP_EXPORT static const Tool& invalid();
+
+    /**
+     * A string containing a brief, human readable description of the Tool object.
+     *
+     * @returns A description of the Tool object as a string.
+     * @since 1.0
+     */
+    LEAP_EXPORT std::string toString() const;
+  };
+
+  /**
+   * The Hand class reports the physical characteristics of a detected hand.
+   *
+   * Hand tracking data includes a palm position and velocity; vectors for
+   * the palm normal and direction to the fingers; properties of a sphere fit
+   * to the hand; and lists of the attached fingers and tools.
+   *
+   * Get Hand objects from a Frame object:
+   *
+   * \include Hand_Get_First.txt
+   *
+   * Note that Hand objects can be invalid, which means that they do not contain
+   * valid tracking data and do not correspond to a physical entity. Invalid Hand
+   * objects can be the result of asking for a Hand object using an ID from an
+   * earlier frame when no Hand objects with that ID exist in the current frame.
+   * A Hand object created from the Hand constructor is also invalid.
+   * Test for validity with the Hand::isValid() function.
+   * @since 1.0
+   */
+  class Hand : public Interface {
+  public:
+    // For internal use only.
+    Hand(HandImplementation*);
+
+    /**
+     * Constructs a Hand object.
+     *
+     * An uninitialized hand is considered invalid.
+     * Get valid Hand objects from a Frame object.
+     *
+     * \include Hand_Hand.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT Hand();
+
+    /**
+     * A unique ID assigned to this Hand object, whose value remains the same
+     * across consecutive frames while the tracked hand remains visible. If
+     * tracking is lost (for example, when a hand is occluded by another hand
+     * or when it is withdrawn from or reaches the edge of the Leap Motion Controller field of view),
+     * the Leap Motion software may assign a new ID when it detects the hand in a future frame.
+     *
+     * Use the ID value with the Frame::hand() function to find this Hand object
+     * in future frames:
+     *
+     * \include Hand_Get_ID.txt
+     *
+     * @returns The ID of this hand.
+     * @since 1.0
+     */
+    LEAP_EXPORT int32_t id() const;
+
+    /**
+     * The Frame associated with this Hand.
+     *
+     * \include Hand_frame.txt
+     *
+     * @returns The associated Frame object, if available; otherwise,
+     * an invalid Frame object is returned.
+     * @since 1.0
+     */
+    LEAP_EXPORT Frame frame() const;
+
+    /**
+     * The list of Pointable objects (fingers and tools) detected in this frame
+     * that are associated with this hand, given in arbitrary order. The list
+     * can be empty if no fingers or tools associated with this hand are detected.
+     *
+     * Use the Pointable::isFinger() function to determine whether or not an
+     * item in the list represents a finger. Use the Pointable::isTool() function
+     * to determine whether or not an item in the list represents a tool.
+     * You can also get only fingers using the Hand::fingers() function or
+     * only tools using the Hand::tools() function.
+     *
+     * \include Hand_Get_Fingers.txt
+     *
+     * @returns The PointableList containing all Pointable objects associated with this hand.
+     * @since 1.0
+     */
+    LEAP_EXPORT PointableList pointables() const;
+
+    /**
+     * The Pointable object with the specified ID associated with this hand.
+     *
+     * Use the Hand::pointable() function to retrieve a Pointable object
+     * associated with this hand using an ID value obtained from a previous frame.
+     * This function always returns a Pointable object, but if no finger or tool
+     * with the specified ID is present, an invalid Pointable object is returned.
+     *
+     * \include Hand_Get_Pointable_ByID.txt
+     *
+     * Note that the ID values assigned to objects persist across frames, but only until 
+     * tracking of that object is lost. If tracking of a finger or tool is lost and subsequently
+     * regained, the new Pointable object representing that finger or tool may have a
+     * different ID than that representing the finger or tool in an earlier frame.
+     *
+     * @param id The ID value of a Pointable object from a previous frame.
+     * @returns The Pointable object with the matching ID if one exists for this
+     * hand in this frame; otherwise, an invalid Pointable object is returned.
+     * @since 1.0
+     */
+    LEAP_EXPORT Pointable pointable(int32_t id) const;
+
+    /**
+     * The list of Finger objects detected in this frame that are attached to
+     * this hand, given in arbitrary order.
+     * The list can be empty if no fingers attached to this hand are detected.
+     *
+     * \include Hand_Get_Fingers.txt
+     *
+     * @returns The FingerList containing all Finger objects attached to this hand.
+     * @since 1.0
+     */
+    LEAP_EXPORT FingerList fingers() const;
+
+    /**
+     * The Finger object with the specified ID attached to this hand.
+     *
+     * Use the Hand::finger() function to retrieve a Finger object attached to
+     * this hand using an ID value obtained from a previous frame.
+     * This function always returns a Finger object, but if no finger
+     * with the specified ID is present, an invalid Finger object is returned.
+     *
+     * \include Hand_finger.txt
+     *
+     * Note that ID values persist across frames, but only until tracking of a
+     * particular object is lost. If tracking of a finger is lost and subsequently
+     * regained, the new Finger object representing that finger may have a
+     * different ID than that representing the finger in an earlier frame.
+     *
+     * @param id The ID value of a Finger object from a previous frame.
+     * @returns The Finger object with the matching ID if one exists for this
+     * hand in this frame; otherwise, an invalid Finger object is returned.
+     * @since 1.0
+     */
+    LEAP_EXPORT Finger finger(int32_t id) const;
+
+    /**
+     * The list of Tool objects detected in this frame that are held by this
+     * hand, given in arbitrary order.
+     * The list can be empty if no tools held by this hand are detected.
+     *
+     * \include Hand_tools.txt
+     *
+     * @returns The ToolList containing all Tool objects held by this hand.
+     * @since 1.0
+     */
+    LEAP_EXPORT ToolList tools() const;
+
+    /**
+     * The Tool object with the specified ID held by this hand.
+     *
+     * Use the Hand::tool() function to retrieve a Tool object held by
+     * this hand using an ID value obtained from a previous frame.
+     * This function always returns a Tool object, but if no tool
+     * with the specified ID is present, an invalid Tool object is returned.
+     *
+     * \include Hand_tool.txt
+     *
+     * Note that ID values persist across frames, but only until tracking of a
+     * particular object is lost. If tracking of a tool is lost and subsequently
+     * regained, the new Tool object representing that tool may have a
+     * different ID than that representing the tool in an earlier frame.
+     *
+     * @param id The ID value of a Tool object from a previous frame.
+     * @returns The Tool object with the matching ID if one exists for this
+     * hand in this frame; otherwise, an invalid Tool object is returned.
+     * @since 1.0
+     */
+    LEAP_EXPORT Tool tool(int32_t id) const;
+
+    /**
+     * The center position of the palm in millimeters from the Leap Motion Controller origin.
+     *
+     * \include Hand_palmPosition.txt
+     *
+     * @returns The Vector representing the coordinates of the palm position.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector palmPosition() const;
+
+    /**
+     * The stabilized palm position of this Hand.
+     *
+     * Smoothing and stabilization is performed in order to make
+     * this value more suitable for interaction with 2D content. The stabilized
+     * position lags behind the palm position by a variable amount, depending
+     * primarily on the speed of movement.
+     * 
+     * \include Hand_stabilizedPalmPosition.txt
+     *
+     * @returns A modified palm position of this Hand object
+     * with some additional smoothing and stabilization applied.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector stabilizedPalmPosition() const;
+
+    /**
+     * The rate of change of the palm position in millimeters/second.
+     *
+     * \include Hand_palmVelocity.txt
+     *
+     * @returns The Vector representing the coordinates of the palm velocity.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector palmVelocity() const;
+
+    /**
+     * The normal vector to the palm. If your hand is flat, this vector will
+     * point downward, or "out" of the front surface of your palm.
+     *
+     * \image html images/Leap_Palm_Vectors.png
+     *
+     * The direction is expressed as a unit vector pointing in the same
+     * direction as the palm normal (that is, a vector orthogonal to the palm).
+     *
+     * You can use the palm normal vector to compute the roll angle of the palm with
+     * respect to the horizontal plane:
+     *
+     * \include Hand_Get_Angles.txt
+     *
+     * @returns The Vector normal to the plane formed by the palm.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector palmNormal() const;
+
+    /**
+     * The direction from the palm position toward the fingers.
+     *
+     * The direction is expressed as a unit vector pointing in the same
+     * direction as the directed line from the palm position to the fingers.
+     *
+     * You can use the palm direction vector to compute the pitch and yaw angles of the palm with
+     * respect to the horizontal plane:
+     *
+     * \include Hand_Get_Angles.txt
+     *
+     * @returns The Vector pointing from the palm position toward the fingers.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector direction() const;
+
+    /**
+     * The center of a sphere fit to the curvature of this hand.
+     *
+     * \include Hand_sphereCenter.txt
+     *
+     * This sphere is placed roughly as if the hand were holding a ball.
+     *
+     * \image html images/Leap_Hand_Ball.png
+     *
+     * @returns The Vector representing the center position of the sphere.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector sphereCenter() const;
+
+    /**
+     * The radius of a sphere fit to the curvature of this hand.
+     *
+     * This sphere is placed roughly as if the hand were holding a ball. Thus the
+     * size of the sphere decreases as the fingers are curled into a fist.
+     *
+     * \include Hand_sphereRadius.txt
+     *
+     * @returns The radius of the sphere in millimeters.
+     * @since 1.0
+     */
+    LEAP_EXPORT float sphereRadius() const;
+
+    /**
+     * The change of position of this hand between the current frame and
+     * the specified frame.
+     *
+     * The returned translation vector provides the magnitude and direction of
+     * the movement in millimeters.
+     *
+     * \include Hand_translation.txt
+     *
+     * If a corresponding Hand object is not found in sinceFrame, or if either
+     * this frame or sinceFrame are invalid Frame objects, then this method
+     * returns a zero vector.
+     *
+     * @param sinceFrame The starting frame for computing the translation.
+     * @returns A Vector representing the heuristically determined change in
+     * hand position between the current frame and that specified in the
+     * sinceFrame parameter.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector translation(const Frame& sinceFrame) const;
+
+    /**
+     * The estimated probability that the hand motion between the current
+     * frame and the specified frame is intended to be a translating motion.
+     *
+     * \include Hand_translationProbability.txt
+     *
+     * If a corresponding Hand object is not found in sinceFrame, or if either
+     * this frame or sinceFrame are invalid Frame objects, then this method
+     * returns zero.
+     *
+     * @param sinceFrame The starting frame for computing the translation.
+     * @returns A value between 0 and 1 representing the estimated probability
+     * that the hand motion between the current frame and the specified frame
+     * is intended to be a translating motion.
+     * @since 1.0
+     */
+    LEAP_EXPORT float translationProbability(const Frame& sinceFrame) const;
+
+    /**
+     * The axis of rotation derived from the change in orientation of this
+     * hand, and any associated fingers and tools, between the current frame
+     * and the specified frame.
+     *
+     * \include Hand_rotationAxis.txt
+     *
+     * The returned direction vector is normalized.
+     *
+     * If a corresponding Hand object is not found in sinceFrame, or if either
+     * this frame or sinceFrame are invalid Frame objects, then this method
+     * returns a zero vector.
+     *
+     * @param sinceFrame The starting frame for computing the relative rotation.
+     * @returns A normalized direction Vector representing the heuristically
+     * determined axis of rotational change of the hand between the current
+     * frame and that specified in the sinceFrame parameter.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector rotationAxis(const Frame& sinceFrame) const;
+
+    /**
+     * The angle of rotation around the rotation axis derived from the change
+     * in orientation of this hand, and any associated fingers and tools,
+     * between the current frame and the specified frame.
+     *
+     * \include Hand_rotationAngle.txt
+     *
+     * The returned angle is expressed in radians measured clockwise around the
+     * rotation axis (using the right-hand rule) between the start and end frames.
+     * The value is always between 0 and pi radians (0 and 180 degrees).
+     *
+     * If a corresponding Hand object is not found in sinceFrame, or if either
+     * this frame or sinceFrame are invalid Frame objects, then the angle of
+     * rotation is zero.
+     *
+     * @param sinceFrame The starting frame for computing the relative rotation.
+     * @returns A positive value representing the heuristically determined
+     * rotational change of the hand between the current frame and that
+     * specified in the sinceFrame parameter.
+     * @since 1.0
+     */
+    LEAP_EXPORT float rotationAngle(const Frame& sinceFrame) const;
+
+    /**
+     * The angle of rotation around the specified axis derived from the change
+     * in orientation of this hand, and any associated fingers and tools,
+     * between the current frame and the specified frame.
+     *
+     * \include Hand_rotationAngle_axis.txt
+     *
+     * The returned angle is expressed in radians measured clockwise around the
+     * rotation axis (using the right-hand rule) between the start and end frames.
+     * The value is always between -pi and pi radians (-180 and 180 degrees).
+     *
+     * If a corresponding Hand object is not found in sinceFrame, or if either
+     * this frame or sinceFrame are invalid Frame objects, then the angle of
+     * rotation is zero.
+     *
+     * @param sinceFrame The starting frame for computing the relative rotation.
+     * @param axis The axis to measure rotation around.
+     * @returns A value representing the heuristically determined rotational
+     * change of the hand between the current frame and that specified in the
+     * sinceFrame parameter around the specified axis.
+     * @since 1.0
+     */
+    LEAP_EXPORT float rotationAngle(const Frame& sinceFrame, const Vector& axis) const;
+
+    /**
+     * The transform matrix expressing the rotation derived from the change
+     * in orientation of this hand, and any associated fingers and tools,
+     * between the current frame and the specified frame.
+     *
+     * \include Hand_rotationMatrix.txt
+     *
+     * If a corresponding Hand object is not found in sinceFrame, or if either
+     * this frame or sinceFrame are invalid Frame objects, then this method
+     * returns an identity matrix.
+     *
+     * @param sinceFrame The starting frame for computing the relative rotation.
+     * @returns A transformation Matrix representing the heuristically determined
+     * rotational change of the hand between the current frame and that specified
+     * in the sinceFrame parameter.
+     * @since 1.0
+     */
+    LEAP_EXPORT Matrix rotationMatrix(const Frame& sinceFrame) const;
+
+    /**
+     * The estimated probability that the hand motion between the current
+     * frame and the specified frame is intended to be a rotating motion.
+     *
+     * \include Hand_rotationProbability.txt
+     *
+     * If a corresponding Hand object is not found in sinceFrame, or if either
+     * this frame or sinceFrame are invalid Frame objects, then this method
+     * returns zero.
+     *
+     * @param sinceFrame The starting frame for computing the relative rotation.
+     * @returns A value between 0 and 1 representing the estimated probability
+     * that the hand motion between the current frame and the specified frame
+     * is intended to be a rotating motion.
+     * @since 1.0
+     */
+    LEAP_EXPORT float rotationProbability(const Frame& sinceFrame) const;
+
+    /**
+     * The scale factor derived from this hand's motion between the current frame
+     * and the specified frame.
+     *
+     * The scale factor is always positive. A value of 1.0 indicates no
+     * scaling took place. Values between 0.0 and 1.0 indicate contraction
+     * and values greater than 1.0 indicate expansion.
+     *
+     * \include Hand_scaleFactor.txt
+     *
+     * The Leap Motion software derives scaling from the relative inward or outward motion of
+     * a hand and its associated fingers and tools (independent of translation
+     * and rotation).
+     *
+     * If a corresponding Hand object is not found in sinceFrame, or if either
+     * this frame or sinceFrame are invalid Frame objects, then this method
+     * returns 1.0.
+     *
+     * @param sinceFrame The starting frame for computing the relative scaling.
+     * @returns A positive value representing the heuristically determined
+     * scaling change ratio of the hand between the current frame and that
+     * specified in the sinceFrame parameter.
+     * @since 1.0
+     */
+    LEAP_EXPORT float scaleFactor(const Frame& sinceFrame) const;
+
+    /**
+     * The estimated probability that the hand motion between the current
+     * frame and the specified frame is intended to be a scaling motion.
+     *
+     * \include Hand_scaleProbability.txt
+     *
+     * If a corresponding Hand object is not found in sinceFrame, or if either
+     * this frame or sinceFrame are invalid Frame objects, then this method
+     * returns zero.
+     *
+     * @param sinceFrame The starting frame for computing the relative scaling.
+     * @returns A value between 0 and 1 representing the estimated probability
+     * that the hand motion between the current frame and the specified frame
+     * is intended to be a scaling motion.
+     * @since 1.0
+     */
+    LEAP_EXPORT float scaleProbability(const Frame& sinceFrame) const;
+
+    /**
+     * The duration of time this Hand has been visible to the Leap Motion Controller.
+     *
+     * \include Hand_timeVisible.txt
+     *
+     * @returns The duration (in seconds) that this Hand has been tracked.
+     * @since 1.0
+     */
+    LEAP_EXPORT float timeVisible() const;
+
+    /**
+     * Reports whether this is a valid Hand object.
+     *
+     * \include Hand_isValid.txt
+     *
+     * @returns True, if this Hand object contains valid tracking data.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isValid() const;
+
+    /**
+     * Returns an invalid Hand object.
+     *
+     * \include Hand_invalid.txt
+     *
+     * You can use the instance returned by this function in comparisons testing
+     * whether a given Hand instance is valid or invalid. (You can also use the
+     * Hand::isValid() function.)
+     *
+     * @returns The invalid Hand instance.
+     * @since 1.0
+     */
+    LEAP_EXPORT static const Hand& invalid();
+
+    /**
+     * Compare Hand object equality.
+     *
+     * \include Hand_operator_equals.txt
+     *
+     * Two Hand objects are equal if and only if both Hand objects represent the
+     * exact same physical hand in the same frame and both Hand objects are valid.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator==(const Hand&) const;
+
+    /**
+     * Compare Hand object inequality.
+     *
+     * \include Hand_operator_not_equals.txt
+     *
+     * Two Hand objects are equal if and only if both Hand objects represent the
+     * exact same physical hand in the same frame and both Hand objects are valid.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator!=(const Hand&) const;
+
+    /**
+     * Writes a brief, human readable description of the Hand object to an output stream.
+     *
+     * \include Hand_operator_stream.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT friend std::ostream& operator<<(std::ostream&, const Hand&);
+
+    /**
+     * A string containing a brief, human readable description of the Hand object.
+     *
+     * @returns A description of the Hand as a string.
+     * @since 1.0
+     */
+    LEAP_EXPORT std::string toString() const;
+  };
+
+  /**
+   * The Gesture class represents a recognized movement by the user.
+   *
+   * The Leap Motion Controller watches the activity within its field of view for certain movement
+   * patterns typical of a user gesture or command. For example, a movement from side to
+   * side with the hand can indicate a swipe gesture, while a finger poking forward
+   * can indicate a screen tap gesture.
+   *
+   * When the Leap Motion software recognizes a gesture, it assigns an ID and adds a
+   * Gesture object to the frame gesture list. For continuous gestures, which
+   * occur over many frames, the Leap Motion software updates the gesture by adding
+   * a Gesture object having the same ID and updated properties in each
+   * subsequent frame.
+   *
+   * **Important:** Recognition for each type of gesture must be enabled using the
+   * Controller::enableGesture() function; otherwise **no gestures are recognized or
+   * reported**.
+   *
+   * \include Gesture_Feature_enable.txt
+   *
+   * Subclasses of Gesture define the properties for the specific movement patterns
+   * recognized by the Leap Motion software.
+   *
+   * The Gesture subclasses for include:
+   *
+   * * CircleGesture -- A circular movement by a finger.
+   * * SwipeGesture -- A straight line movement by the hand with fingers extended.
+   * * ScreenTapGesture -- A forward tapping movement by a finger.
+   * * KeyTapGesture -- A downward tapping movement by a finger.
+   *
+   * Circle and swipe gestures are continuous and these objects can have a
+   * state of start, update, and stop.
+   *
+   * The screen tap gesture is a discrete gesture. The Leap Motion software only creates a single
+   * ScreenTapGesture object for each tap and it always has a stop state.
+   *
+   * Get valid Gesture instances from a Frame object. You can get a list of gestures
+   * with the Frame::gestures() method. You can get a list of gestures since a
+   * specified frame with the `Frame::gestures(const Frame&)` method. You can also
+   * use the `Frame::gesture()` method to find a gesture in the current frame using
+   * an ID value obtained in a previous frame.
+   *
+   * Gesture objects can be invalid. For example, when you get a gesture by ID
+   * using `Frame::gesture()`, and there is no gesture with that ID in the current
+   * frame, then `gesture()` returns an Invalid Gesture object (rather than a null
+   * value). Always check object validity in situations where a gesture might be
+   * invalid.
+   *
+   * The following keys can be used with the Config class to configure the gesture
+   * recognizer:
+   *
+   * Key string | Value type | Default value | Units
+   * -----------|------------|---------------|------
+   * Gesture.Circle.MinRadius | float | 5.0 | mm
+   * Gesture.Circle.MinArc | float | 1.5*pi | radians
+   * Gesture.Swipe.MinLength | float | 150 | mm
+   * Gesture.Swipe.MinVelocity | float | 1000 | mm/s
+   * Gesture.KeyTap.MinDownVelocity | float | 50 | mm/s
+   * Gesture.KeyTap.HistorySeconds | float | 0.1 | s
+   * Gesture.KeyTap.MinDistance | float | 5.0 | mm
+   * Gesture.ScreenTap.MinForwardVelocity  | float | 50 | mm/s
+   * Gesture.ScreenTap.HistorySeconds | float | 0.1 | s
+   * Gesture.ScreenTap.MinDistance | float | 3.0 | mm
+   * @since 1.0
+   */
+  class Gesture : public Interface {
+  public:
+    // For internal use only.
+    Gesture(GestureImplementation*);
+
+    /**
+     * The supported types of gestures.
+     * @since 1.0
+     */
+    enum Type {
+      /**
+       * An invalid type.
+       * @since 1.0
+       */
+      TYPE_INVALID    = -1,
+      /**
+       * A straight line movement by the hand with fingers extended.
+       * @since 1.0
+       */
+      TYPE_SWIPE      = 1,
+      /**
+       * A circular movement by a finger.
+       * @since 1.0
+       */
+      TYPE_CIRCLE     = 4,
+      /**
+       * A forward tapping movement by a finger.
+       * @since 1.0
+       */
+      TYPE_SCREEN_TAP = 5,
+      /**
+       * A downward tapping movement by a finger.
+       * @since 1.0
+       */
+      TYPE_KEY_TAP    = 6
+    };
+
+    /**
+     * The possible gesture states.
+     * @since 1.0
+     */
+    enum State {
+      /**
+       * An invalid state
+       * @since 1.0
+       */
+      STATE_INVALID = -1,
+      /**
+       * The gesture is starting. Just enough has happened to recognize it.
+       * @since 1.0
+       */
+      STATE_START   = 1,
+      /**
+       * The gesture is in progress. (Note: not all gestures have updates).
+       * @since 1.0
+       */
+      STATE_UPDATE  = 2,
+      /**
+       * The gesture has completed or stopped.
+       * @since 1.0
+       */
+      STATE_STOP    = 3,
+    };
+
+    /**
+     * Constructs a new Gesture object.
+     *
+     * An uninitialized Gesture object is considered invalid. Get valid instances
+     * of the Gesture class, which will be one of the Gesture subclasses, from a
+     * Frame object.
+     * @since 1.0
+     */
+    LEAP_EXPORT Gesture();
+
+    /**
+     * Constructs a new copy of an Gesture object.
+     *
+     * \include Gesture_Gesture_copy.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT Gesture(const Gesture& rhs);
+
+    /**
+     * The gesture type.
+     *
+     * \include Gesture_type.txt
+     *
+     * @returns Gesture::Type A value from the Gesture::Type enumeration.
+     * @since 1.0
+     */
+    LEAP_EXPORT Type type() const;
+
+    /**
+     * The gesture state.
+     *
+     * Recognized movements occur over time and have a beginning, a middle,
+     * and an end. The 'state()' attribute reports where in that sequence this
+     * Gesture object falls.
+     *
+     * \include Gesture_state.txt
+     *
+     * @returns Gesture::State A value from the Gesture::State enumeration.
+     * @since 1.0
+     */
+    LEAP_EXPORT State state() const;
+
+    /**
+     * The gesture ID.
+     *
+     * All Gesture objects belonging to the same recognized movement share the
+     * same ID value. Use the ID value with the Frame::gesture() method to
+     * find updates related to this Gesture object in subsequent frames.
+     *
+     * \include Gesture_id.txt
+     *
+     * @returns int32_t the ID of this Gesture.
+     * @since 1.0
+     */
+    LEAP_EXPORT int32_t id() const;
+
+    /**
+     * The elapsed duration of the recognized movement up to the
+     * frame containing this Gesture object, in microseconds.
+     *
+     * \include Gesture_duration.txt
+     *
+     * The duration reported for the first Gesture in the sequence (with the
+     * STATE_START state) will typically be a small positive number since
+     * the movement must progress far enough for the Leap Motion software to recognize it as
+     * an intentional gesture.
+     *
+     * @return int64_t the elapsed duration in microseconds.
+     * @since 1.0
+     */
+    LEAP_EXPORT int64_t duration() const;
+
+    /**
+     * The elapsed duration in seconds.
+     *
+     * \include Gesture_durationSeconds.txt
+     *
+     * @see duration()
+     * @return float the elapsed duration in seconds.
+     * @since 1.0
+     */
+    LEAP_EXPORT float durationSeconds() const;
+
+    /**
+     * The Frame containing this Gesture instance.
+     *
+     * \include Gesture_frame.txt
+     _
+     * @return Frame The parent Frame object.
+     * @since 1.0
+     */
+    LEAP_EXPORT Frame frame() const;
+
+    /**
+     * The list of hands associated with this Gesture, if any.
+     *
+     * \include Gesture_hands.txt
+     *
+     * If no hands are related to this gesture, the list is empty.
+     *
+     * @return HandList the list of related Hand objects.
+     * @since 1.0
+     */
+    LEAP_EXPORT HandList hands() const;
+
+    /**
+     * The list of fingers and tools associated with this Gesture, if any.
+     *
+     * If no Pointable objects are related to this gesture, the list is empty.
+     *
+     * \include Gesture_pointables.txt
+     *
+     * @return PointableList the list of related Pointable objects.
+     * @since 1.0
+     */
+    LEAP_EXPORT PointableList pointables() const;
+
+    /**
+     * Reports whether this Gesture instance represents a valid Gesture.
+     *
+     * An invalid Gesture object does not represent a snapshot of a recognized
+     * movement. Invalid Gesture objects are returned when a valid object cannot
+     * be provided. For example, when you get an gesture by ID
+     * using Frame::gesture(), and there is no gesture with that ID in the current
+     * frame, then gesture() returns an Invalid Gesture object (rather than a null
+     * value). Always check object validity in situations where an gesture might be
+     * invalid.
+     *
+     * \include Gesture_isValid.txt
+     *
+     * @returns bool True, if this is a valid Gesture instance; false, otherwise.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isValid() const;
+
+    /**
+     * Compare Gesture object equality.
+     *
+     * \include Gesture_operator_equals.txt
+     *
+     * Two Gestures are equal if they represent the same snapshot of the same
+     * recognized movement.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator==(const Gesture& rhs) const;
+
+    /**
+     * Compare Gesture object inequality.
+     *
+     * \include Gesture_operator_not_equals.txt
+     *
+     * Two Gestures are equal only if they represent the same snapshot of the same
+     * recognized movement.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator!=(const Gesture& rhs) const;
+
+    /**
+     * A string containing a brief, human-readable description of this
+     * Gesture.
+     *
+     * \include Gesture_toString.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT std::string toString() const;
+
+    /**
+     * Returns an invalid Gesture object.
+     *
+     * You can use the instance returned by this function in comparisons testing
+     * whether a given Gesture instance is valid or invalid. (You can also use the
+     * Gesture::isValid() function.)
+     *
+     * \include Gesture_invalid.txt
+     *
+     * @returns The invalid Gesture instance.
+     * @since 1.0
+     */
+    LEAP_EXPORT static const Gesture& invalid();
+  };
+
+  /**
+   * The SwipeGesture class represents a swiping motion of a finger or tool.
+   *
+   * \image html images/Leap_Gesture_Swipe.png
+   *
+   * **Important:** To use swipe gestures in your application, you must enable
+   * recognition of the swipe gesture. You can enable recognition with:
+   *
+   * \include Gesture_Swipe_Enable.txt
+   *
+   * Swipe gestures are continuous.
+   *
+   * You can set the minimum length and velocity required for a movement
+   * to be recognized as a swipe using the config attribute of a connected
+   * Controller object. Use the following keys to configure swipe recognition:
+   *
+   * Key string | Value type | Default value | Units
+   * -----------|------------|---------------|------
+   * Gesture.Swipe.MinLength | float | 150 | mm
+   * Gesture.Swipe.MinVelocity | float | 1000 | mm/s
+   *
+   * The following example demonstrates how to set the swipe configuration
+   * parameters:
+   *
+   * \include Gesture_Swipe_Params.txt
+   * @since 1.0
+   */
+  class SwipeGesture : public Gesture
+  {
+  public:
+    /**
+     * The swipe gesture type.
+     *
+     * \include SwipeGesture_classType.txt
+     *
+     * @returns Type The type value designating a swipe gesture.
+     * @since 1.0
+     */
+    static Type classType() { return TYPE_SWIPE; }
+
+    LEAP_EXPORT SwipeGesture();
+
+    /**
+     * Constructs a SwipeGesture object from an instance of the Gesture class.
+     *
+     * \include SwipeGesture_SwipeGesture.txt
+     *
+     * @param rhs The Gesture instance to specialize. This Gesture instance must
+     * be a SwipeGesture object.
+     * @since 1.0
+     */
+    LEAP_EXPORT SwipeGesture(const Gesture& rhs);
+
+    /**
+     * The position where the swipe began.
+     *
+     * \include SwipeGesture_startPosition.txt
+     *
+     * @returns Vector The starting position within the Leap Motion frame of
+     * reference, in mm.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector startPosition() const;
+
+    /**
+     * The current position of the swipe.
+     *
+     * \include SwipeGesture_position.txt
+     *
+     * @returns Vector The current swipe position within the Leap Motion frame of
+     * reference, in mm.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector position() const;
+
+    /**
+     * The unit direction vector parallel to the swipe motion.
+     *
+     * \include SwipeGesture_direction.txt
+     *
+     * You can compare the components of the vector to classify the swipe as
+     * appropriate for your application. For example, if you are using swipes
+     * for two dimensional scrolling, you can compare the x and y values to
+     * determine if the swipe is primarily horizontal or vertical.
+     *
+     * @returns Vector The unit direction vector representing the swipe
+     * motion.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector direction() const;
+
+    /**
+     * The swipe speed in mm/second.
+     *
+     * \include SwipeGesture_speed.txt
+     *
+     * @returns float The speed of the finger performing the swipe gesture in
+     * millimeters per second.
+     * @since 1.0
+     */
+    LEAP_EXPORT float speed() const;
+
+    /**
+     * The finger performing the swipe gesture.
+     *
+     * \include SwipeGesture_pointable.txt
+     *
+     * @returns Pointable A Pointable object representing the swiping finger.
+     * @since 1.0
+     */
+    LEAP_EXPORT Pointable pointable() const;
+  };
+
+  /**
+   * The CircleGesture classes represents a circular finger movement.
+   *
+   * A circle movement is recognized when the tip of a finger draws a circle
+   * within the Leap Motion Controller field of view.
+   *
+   * \image html images/Leap_Gesture_Circle.png
+   *
+   * **Important:** To use circle gestures in your application, you must enable
+   * recognition of the circle gesture. You can enable recognition with:
+   *
+   * \include Gesture_Circle_Enable.txt
+   *
+   * Circle gestures are continuous. The CircleGesture objects for the gesture have
+   * three possible states:
+   *
+   * * State::STATE_START -- The circle gesture has just started. The movement has
+   *   progressed far enough for the recognizer to classify it as a circle.
+   * * State::STATE_UPDATE -- The circle gesture is continuing.
+   * * State::STATE_STOP -- The circle gesture is finished.
+   *
+   * You can set the minimum radius and minimum arc length required for a movement
+   * to be recognized as a circle using the config attribute of a connected
+   * Controller object. Use the following keys to configure circle recognition:
+   *
+   * Key string | Value type | Default value | Units
+   * -----------|------------|---------------|------
+   * Gesture.Circle.MinRadius | float | 5.0 | mm
+   * Gesture.Circle.MinArc | float | 1.5*pi | radians
+   *
+   * The following example demonstrates how to set the circle configuration
+   * parameters:
+   *
+   * \include Gesture_Circle_Params.txt
+   *
+   * @since 1.0
+   */
+  class CircleGesture : public Gesture
+  {
+  public:
+    /**
+     * The circle gesture type.
+     *
+     * \include CircleGesture_classType.txt
+     *
+     * @returns Type The type value designating a circle gesture.
+     * @since 1.0
+     */
+    static Type classType() { return TYPE_CIRCLE; }
+
+    /**
+     * Constructs a new CircleGesture object.
+     *
+     * An uninitialized CircleGesture object is considered invalid. Get valid instances
+     * of the CircleGesture class from a Frame object.
+     * @since 1.0
+     */
+    LEAP_EXPORT CircleGesture();
+
+    /**
+     * Constructs a CircleGesture object from an instance of the Gesture class.
+     *
+     * \include CircleGesture_CircleGesture.txt
+     *
+     * @param rhs The Gesture instance to specialize. This Gesture instance must
+     * be a CircleGesture object.
+     * @since 1.0
+     */
+    LEAP_EXPORT CircleGesture(const Gesture& rhs);
+
+    /**
+     * The center point of the circle within the Leap Motion frame of reference.
+     *
+     * \include CircleGesture_center.txt
+     * @returns Vector The center of the circle in mm from the Leap Motion origin.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector center() const;
+
+    /**
+     * Returns the normal vector for the circle being traced.
+     *
+     * If you draw the circle clockwise, the normal vector points in the same
+     * general direction as the pointable object drawing the circle. If you draw
+     * the circle counterclockwise, the normal points back toward the
+     * pointable. If the angle between the normal and the pointable object
+     * drawing the circle is less than 90 degrees, then the circle is clockwise.
+     *
+     * \include Gesture_Circle_Direction.txt
+     *
+     * @return Vector the normal vector for the circle being traced
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector normal() const;
+
+    /**
+     * The number of times the finger tip has traversed the circle.
+     *
+     * Progress is reported as a positive number of the number. For example,
+     * a progress value of .5 indicates that the finger has gone halfway
+     * around, while a value of 3 indicates that the finger has gone around
+     * the the circle three times.
+     *
+     * \include CircleGesture_progress.txt
+     *
+     * Progress starts where the circle gesture began. Since the circle
+     * must be partially formed before the Leap Motion software can recognize it, progress
+     * will be greater than zero when a circle gesture first appears in the
+     * frame.
+     *
+     * @returns float A positive number indicating the gesture progress.
+     * @since 1.0
+     */
+    LEAP_EXPORT float progress() const;
+
+    /**
+     * The radius of the circle.
+     *
+     * \include CircleGesture_radius.txt
+     *
+     * @returns The circle radius in mm.
+     * @since 1.0
+     */
+    LEAP_EXPORT float radius() const;
+
+    /**
+     * The finger performing the circle gesture.
+     *
+     * \include CircleGesture_pointable.txt
+     *
+     * @returns Pointable A Pointable object representing the circling finger.
+     * @since 1.0
+     */
+    LEAP_EXPORT Pointable pointable() const;
+  };
+
+  /**
+   * The ScreenTapGesture class represents a tapping gesture by a finger or tool.
+   *
+   * A screen tap gesture is recognized when the tip of a finger pokes forward
+   * and then springs back to approximately the original postion, as if
+   * tapping a vertical screen. The tapping finger must pause briefly before beginning the tap.
+   *
+   * \image html images/Leap_Gesture_Tap2.png
+   *
+   * **Important:** To use screen tap gestures in your application, you must enable
+   * recognition of the screen tap gesture. You can enable recognition with:
+   *
+   * \include Gesture_ScreenTap_Enable.txt
+   *
+   * ScreenTap gestures are discrete. The ScreenTapGesture object representing a tap always
+   * has the state, STATE_STOP. Only one ScreenTapGesture object is created for each
+   * screen tap gesture recognized.
+   *
+   * You can set the minimum finger movement and velocity required for a movement
+   * to be recognized as a screen tap as well as adjust the detection window for
+   * evaluating the movement using the config attribute of a connected
+   * Controller object. Use the following keys to configure screen tap recognition:
+   *
+   * Key string | Value type | Default value | Units
+   * -----------|------------|---------------|------
+   * Gesture.ScreenTap.MinForwardVelocity  | float | 50 | mm/s
+   * Gesture.ScreenTap.HistorySeconds | float | 0.1 | s
+   * Gesture.ScreenTap.MinDistance | float | 3.0 | mm
+   *
+   * The following example demonstrates how to set the screen tap configuration
+   * parameters:
+   *
+   * \include Gesture_ScreenTap_Params.txt
+   * @since 1.0
+   */
+  class ScreenTapGesture : public Gesture
+  {
+  public:
+    /**
+     * The screen tap gesture type.
+     *
+     * \include ScreenTapGesture_classType.txt
+     *
+     * @returns Type The type value designating a screen tap gesture.
+     * @since 1.0
+     */
+    static Type classType() { return TYPE_SCREEN_TAP; }
+
+    /**
+     * Constructs a new ScreenTapGesture object.
+     *
+     * An uninitialized ScreenTapGesture object is considered invalid. Get valid instances
+     * of the ScreenTapGesture class from a Frame object.
+     * @since 1.0
+     */
+    LEAP_EXPORT ScreenTapGesture();
+
+    /**
+     * Constructs a ScreenTapGesture object from an instance of the Gesture class.
+     *
+     * \include ScreenTapGesture_ScreenTapGesture.txt
+     *
+     * @param rhs The Gesture instance to specialize. This Gesture instance must
+     * be a ScreenTapGesture object.
+     * @since 1.0
+     */
+    LEAP_EXPORT ScreenTapGesture(const Gesture& rhs);
+
+    /**
+     * The position where the screen tap is registered.
+     *
+     * \include ScreenTapGesture_position.txt
+     *
+     * @return Vector A Vector containing the coordinates of screen tap location.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector position() const;
+
+    /**
+     * The direction of finger tip motion.
+     *
+     * \include ScreenTapGesture_direction.txt
+     *
+     * @returns Vector A unit direction vector.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector direction() const;
+
+    /**
+     * The progess value is always 1.0 for a screen tap gesture.
+     *
+     * @returns float The value 1.0.
+     * @since 1.0
+     */
+    LEAP_EXPORT float progress() const;
+
+    /**
+     * The finger performing the screen tap gesture.
+     *
+     * \include ScreenTapGesture_pointable.txt
+     *
+     * @returns Pointable A Pointable object representing the tapping finger.
+     * @since 1.0
+     */
+    LEAP_EXPORT Pointable pointable() const;
+  };
+
+  /**
+   * The KeyTapGesture class represents a tapping gesture by a finger or tool.
+   *
+   * A key tap gesture is recognized when the tip of a finger rotates down toward the
+   * palm and then springs back to approximately the original postion, as if
+   * tapping. The tapping finger must pause briefly before beginning the tap.
+   *
+   * \image html images/Leap_Gesture_Tap.png
+   *
+   * **Important:** To use key tap gestures in your application, you must enable
+   * recognition of the key tap gesture. You can enable recognition with:
+   *
+   * \include Gesture_KeyTap_Enable.txt
+   *
+   * Key tap gestures are discrete. The KeyTapGesture object representing a tap always
+   * has the state, STATE_STOP. Only one KeyTapGesture object is created for each
+   * key tap gesture recognized.
+   *
+   * You can set the minimum finger movement and velocity required for a movement
+   * to be recognized as a key tap as well as adjust the detection window for
+   * evaluating the movement using the config attribute of a connected
+   * Controller object. Use the following configuration keys to configure key tap
+   * recognition:
+   *
+   * Key string | Value type | Default value | Units
+   * -----------|------------|---------------|------
+   * Gesture.KeyTap.MinDownVelocity | float | 50 | mm/s
+   * Gesture.KeyTap.HistorySeconds | float | 0.1 | s
+   * Gesture.KeyTap.MinDistance | float | 5.0 | mm
+   *
+   * The following example demonstrates how to set the key tap configuration
+   * parameters:
+   *
+   * \include Gesture_KeyTap_Params.txt
+   *
+   * @since 1.0
+   */
+  class KeyTapGesture : public Gesture
+  {
+  public:
+    /**
+     * The key tap gesture type.
+     *
+     * \include KeyTapGesture_classType.txt
+     *
+     * @returns Type The type value designating a key tap gesture.
+     * @since 1.0
+     */
+    static Type classType() { return TYPE_KEY_TAP; }
+
+    /**
+     * Constructs a new KeyTapGesture object.
+     *
+     * An uninitialized KeyTapGesture object is considered invalid. Get valid instances
+     * of the KeyTapGesture class from a Frame object.
+     * @since 1.0
+     */
+    LEAP_EXPORT KeyTapGesture();
+
+    /**
+     * Constructs a KeyTapGesture object from an instance of the Gesture class.
+     *
+     * \include KeyTapGesture_KeyTapGesture.txt
+     *
+     * @param rhs The Gesture instance to specialize. This Gesture instance must
+     * be a KeyTapGesture object.
+     * @since 1.0
+     */
+    LEAP_EXPORT KeyTapGesture(const Gesture& rhs);
+
+    /**
+     * The position where the key tap is registered.
+     *
+     * \include KeyTapGesture_position.txt
+     *
+     * @return Vector A Vector containing the coordinates of tap location.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector position() const;
+
+    /**
+     * The direction of finger tip motion.
+     *
+     * \include KeyTapGesture_direction.txt
+     *
+     * @returns Vector A unit direction vector if the finger tip is moving;
+     * otherwise, a zero-vector.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector direction() const;
+
+    /**
+     * The progess value is always 1.0 for a key tap gesture.
+     *
+     * @returns float The value 1.0.
+     * @since 1.0
+     */
+    LEAP_EXPORT float progress() const;
+
+    /**
+     * The finger performing the key tap gesture.
+     *
+     * \include KeyTapGesture_pointable.txt
+     *
+     * @returns Pointable A Pointable object representing the tapping finger.
+     * @since 1.0
+     */
+    LEAP_EXPORT Pointable pointable() const;
+  };
+
+  /*
+   * The Screen class is currently unsupported.
+   *
+   * We are re-evaluating this feature due to the cumbersome location process
+   * required to use it and the amount of confusion about the feature's purpose.
+   *
+   * The Screen class represents a computer monitor screen.
+   *
+   * The Screen class reports characteristics describing the position and
+   * orientation of the monitor screen within the Leap Motion coordinate system. These
+   * characteristics include the bottom-left corner position of the screen,
+   * direction vectors for the horizontal and vertical axes of the screen, and
+   * the screen's normal vector. The screen must be properly registered with the
+   * Screen Locator for the Leap Motion software to report these characteristics accurately.
+   * The Screen class also reports the size of the screen in pixels, using
+   * information obtained from the operating system. (Run the Screen Locator
+   * from the Leap Motion Settings dialog, on the Screen page.)
+   *
+   * You can get the point of intersection between the screen and a ray
+   * projected from a Pointable object using the Screen::intersect() function.
+   * Likewise, you can get the closest point on the screen to a point in space
+   * using the Screen::project() function. Again, the screen location
+   * must be registered with the Screen Locator for these functions to
+   * return accurate values.
+   *
+   * Note that Screen objects can be invalid, which means that they do not contain
+   * valid screen coordinate data and do not correspond to a physical entity.
+   * Test for validity with the Screen::isValid() function.
+   * @since 1.0
+   */
+  class Screen : public Interface {
+  public:
+    // For internal use only.
+    Screen(ScreenImplementation*);
+
+    /**
+     * Constructs a Screen object.
+     *
+     * An uninitialized screen is considered invalid.
+     * Get valid Screen objects from a ScreenList object obtained using the
+     * Controller::locatedScreens() method.
+     * @since 1.0
+     */
+    LEAP_EXPORT Screen();
+
+    /**
+     * A unique identifier for this screen based on the screen
+     * information in the configuration. A default screen with ID, *0*,
+     * always exists and contains default characteristics, even if no screens
+     * have been located.
+     * @since 1.0
+     */
+    LEAP_EXPORT int32_t id() const;
+
+    /**
+     * Returns the intersection between this screen and a ray projecting from a
+     * Pointable object.
+     *
+     * The projected ray emanates from the Pointable tipPosition along the
+     * Pointable's direction vector.
+     *
+     * Set the normalize parameter to true to request the intersection point in
+     * normalized screen coordinates. Normalized screen coordinates are usually
+     * values between 0 and 1, where 0 represents the screen's origin at the
+     * bottom-left corner and 1 represents the opposite edge (either top or
+     * right). When you request normalized coordinates, the z-component of the
+     * returned vector is zero. Multiply a normalized coordinate by the values
+     * returned by Screen::widthPixels() or Screen::heightPixels() to calculate
+     * the screen position in pixels (remembering that many other computer
+     * graphics coordinate systems place the origin in the top-left corner).
+     *
+     * Set the normalize parameter to false to request the intersection point
+     * in Leap Motion coordinates (millimeters from the Leap Motion origin).
+     *
+     * If the Pointable object points outside the screen's border (but still
+     * intersects the plane in which the screen lies), the returned intersection
+     * point is clamped to the nearest point on the edge of the screen.
+     *
+     * You can use the clampRatio parameter to contract or expand the area in
+     * which you can point. For example, if you set the clampRatio parameter to
+     * 0.5, then the positions reported for intersection points outside the
+     * central 50% of the screen are moved to the border of this smaller area.
+     * If, on the other hand, you expanded the area by setting clampRatio to
+     * a value such as 3.0, then you could point well outside screen's physical
+     * boundary before the intersection points would be clamped. The positions
+     * for any points clamped would also be placed on this larger outer border.
+     * The positions reported for any intersection points inside the clamping
+     * border are unaffected by clamping.
+     *
+     * \include Screen_Normalized_2.txt
+     *
+     * If the Pointable object does not point toward the plane of the screen
+     * (i.e. it is pointing parallel to or away from the screen), then the
+     * components of the returned vector are all set to NaN (not-a-number).
+     *
+     * @param pointable The Pointable object to check for screen intersection.
+     *
+     * @param normalize If true, return normalized coordinates representing
+     * the intersection point as a percentage of the screen's width and height.
+     * If false, return Leap Motion coordinates (millimeters from the Leap Motion origin,
+     * which is located at the center of the top surface of the Leap Motion Controller).
+     * If true and the clampRatio parameter is set to 1.0, coordinates will be
+     * of the form (0..1, 0..1, 0). Setting the clampRatio to a different value
+     * changes the range for normalized coordinates. For example, a clampRatio
+     * of 5.0 changes the range of values to be of the form (-2..3, -2..3, 0).
+     *
+     * @param clampRatio Adjusts the clamping border around this screen.
+     * By default this ratio is 1.0, and the border corresponds to the actual
+     * boundaries of the screen. Setting clampRatio to 0.5 would reduce the
+     * interaction area. Likewise, setting the ratio to 2.0 would increase the
+     * interaction area, adding 50% around each edge of the physical monitor.
+     * Intersection points outside the interaction area are repositioned to
+     * the closest point on the clamping border before the vector is returned.
+     *
+     * @returns A Vector containing the coordinates of the intersection between
+     * this screen and a ray projecting from the specified Pointable object.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector intersect(const Pointable& pointable, bool normalize, float clampRatio = 1.0f) const;
+
+    /**
+     * Returns the intersection between this screen and a ray projecting from
+     * the specified position along the specified direction.
+     *
+     * Set the normalize parameter to true to request the intersection point in
+     * normalized screen coordinates. Normalized screen coordinates are usually
+     * values between 0 and 1, where 0 represents the screen's origin at the
+     * bottom-left corner and 1 represents the opposite edge (either top or
+     * right). When you request normalized coordinates, the z-component of the
+     * returned vector is zero. Multiply a normalized coordinate by the values
+     * returned by Screen::widthPixels() or Screen::heightPixels() to calculate
+     * the screen position in pixels (remembering that many other computer
+     * graphics coordinate systems place the origin in the top-left corner).
+     *
+     * Set the normalize parameter to false to request the intersection point
+     * in Leap Motion coordinates (millimeters from the Leap Motion origin).
+     *
+     * If the specified ray points outside the screen's border (but still
+     * intersects the plane in which the screen lies), the returned intersection
+     * point is clamped to the nearest point on the edge of the screen.
+     *
+     * You can use the clampRatio parameter to contract or expand the area in
+     * which you can point. For example, if you set the clampRatio parameter to
+     * 0.5, then the positions reported for intersection points outside the
+     * central 50% of the screen are moved to the border of this smaller area.
+     * If, on the other hand, you expanded the area by setting clampRatio to
+     * a value such as 3.0, then you could point well outside screen's physical
+     * boundary before the intersection points would be clamped. The positions
+     * for any points clamped would also be placed on this larger outer border.
+     * The positions reported for any intersection points inside the clamping
+     * border are unaffected by clamping.
+     *
+     * If the specified ray does not point toward the plane of the screen
+     * (i.e. it is pointing parallel to or away from the screen), then the
+     * components of the returned vector are all set to NaN (not-a-number).
+     *
+     * @param position The position from which to check for screen intersection.
+     * @param direction The direction in which to check for screen intersection.
+     *
+     * @param normalize If true, return normalized coordinates representing
+     * the intersection point as a percentage of the screen's width and height.
+     * If false, return Leap Motion coordinates (millimeters from the Leap Motion origin,
+     * which is located at the center of the top surface of the Leap Motion Controller).
+     * If true and the clampRatio parameter is set to 1.0, coordinates will be
+     * of the form (0..1, 0..1, 0). Setting the clampRatio to a different value
+     * changes the range for normalized coordinates. For example, a clampRatio
+     * of 5.0 changes the range of values to be of the form (-2..3, -2..3, 0).
+     *
+     * @param clampRatio Adjusts the clamping border around this screen.
+     * By default this ratio is 1.0, and the border corresponds to the actual
+     * boundaries of the screen. Setting clampRatio to 0.5 would reduce the
+     * interaction area. Likewise, setting the ratio to 2.0 would increase the
+     * interaction area, adding 50% around each edge of the physical monitor.
+     * Intersection points outside the interaction area are repositioned to
+     * the closest point on the clamping border before the vector is returned.
+     *
+     * @returns A Vector containing the coordinates of the intersection between
+     * this screen and a ray projecting from the specified position in the
+     * specified direction.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector intersect(const Vector& position, const Vector& direction, bool normalize, float clampRatio = 1.0f) const;
+
+    /**
+     * Returns the projection from the specified position onto this screen.
+     *
+     * Set the normalize parameter to true to request the projection point in
+     * normalized screen coordinates. Normalized screen coordinates are usually
+     * values between 0 and 1, where 0 represents the screen's origin at the
+     * bottom-left corner and 1 represents the opposite edge (either top or
+     * right). When you request normalized coordinates, the z-component of the
+     * returned vector is zero. Multiply a normalized coordinate by the values
+     * returned by Screen::widthPixels() or Screen::heightPixels() to calculate
+     * the screen position in pixels (remembering that many other computer
+     * graphics coordinate systems place the origin in the top-left corner).
+     *
+     * Set the normalize parameter to false to request the projection point
+     * in Leap Motion coordinates (millimeters from the Leap Motion origin).
+     *
+     * If the specified point projects outside the screen's border, the returned
+     * projection point is clamped to the nearest point on the edge of the screen.
+     *
+     * You can use the clampRatio parameter to contract or expand the area in
+     * which you can point. For example, if you set the clampRatio parameter to
+     * 0.5, then the positions reported for projection points outside the
+     * central 50% of the screen are moved to the border of this smaller area.
+     * If, on the other hand, you expanded the area by setting clampRatio to
+     * a value such as 3.0, then you could point well outside screen's physical
+     * boundary before the projection points would be clamped. The positions
+     * for any points clamped would also be placed on this larger outer border.
+     * The positions reported for any projection points inside the clamping
+     * border are unaffected by clamping.
+     *
+     * @param position The position from which to project onto this screen.
+     *
+     * @param normalize If true, return normalized coordinates representing
+     * the projection point as a percentage of the screen's width and height.
+     * If false, return Leap Motion coordinates (millimeters from the Leap Motion origin,
+     * which is located at the center of the top surface of the Leap Motion Controller).
+     * If true and the clampRatio parameter is set to 1.0, coordinates will be
+     * of the form (0..1, 0..1, 0). Setting the clampRatio to a different value
+     * changes the range for normalized coordinates. For example, a clampRatio
+     * of 5.0 changes the range of values to be of the form (-2..3, -2..3, 0).
+     *
+     * @param clampRatio Adjusts the clamping border around this screen.
+     * By default this ratio is 1.0, and the border corresponds to the actual
+     * boundaries of the screen. Setting clampRatio to 0.5 would reduce the
+     * interaction area. Likewise, setting the ratio to 2.0 would increase the
+     * interaction area, adding 50% around each edge of the physical monitor.
+     * Projection points outside the interaction area are repositioned to
+     * the closest point on the clamping border before the vector is returned.
+     *
+     * @returns A Vector containing the coordinates of the projection between
+     * this screen and a ray projecting from the specified position onto the
+     * screen along its normal vector.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector project(const Vector& position, bool normalize, float clampRatio = 1.0f) const;
+
+    /**
+     * A Vector representing the horizontal axis of this Screen within the
+     * Leap Motion coordinate system.
+     *
+     * The magnitude of this vector estimates the physical width of this Screen
+     * in millimeters. The direction of this vector is parallel to the bottom
+     * edge of the screen and points toward the right edge of the screen.
+     *
+     * Together, horizontalAxis(), verticalAxis(), and bottomLeftCorner()
+     * describe the physical position, size and orientation of this Screen.
+     *
+     * @returns A Vector representing the bottom, horizontal edge of this Screen.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector horizontalAxis() const;
+
+    /**
+     * A Vector representing the vertical axis of this Screen within the
+     * Leap Motion coordinate system.
+     *
+     * The magnitude of this vector estimates the physical height of this Screen
+     * in millimeters. The direction of this vector is parallel to the left
+     * edge of the screen and points toward the top edge of the screen.
+     *
+     * Together, horizontalAxis(), verticalAxis(), and bottomLeftCorner()
+     * describe the physical position, size and orientation of this screen.
+     *
+     * @returns A Vector representing the left, vertical edge of this Screen.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector verticalAxis() const;
+
+    /**
+     * A Vector representing the bottom left corner of this Screen within the
+     * Leap Motion coordinate system.
+     *
+     * The point represented by this vector defines the origin of the screen
+     * in the Leap Motion coordinate system.
+     *
+     * Together, horizontalAxis(), verticalAxis(), and bottomLeftCorner()
+     * describe the physical position, size and orientation of this Screen.
+     *
+     * @returns A Vector containing the coordinates of the bottom-left corner
+     * of this Screen.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector bottomLeftCorner() const;
+
+    /**
+     * A Vector normal to the plane in which this Screen lies.
+     *
+     * The normal vector is a unit direction vector orthogonal to the screen's
+     * surface plane. It points toward a viewer positioned for typical use of
+     * the monitor.
+     *
+     * @returns A Vector representing this Screen's normal vector.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector normal() const;
+
+    /**
+     * The horizontal resolution of this screen, in pixels.
+     *
+     * @returns The width of this Screen in pixels.
+     * @since 1.0
+     */
+    LEAP_EXPORT int widthPixels() const;
+
+    /**
+     * The vertical resolution of this screen, in pixels.
+     *
+     * @returns The height of this Screen in pixels.
+     * @since 1.0
+     */
+    LEAP_EXPORT int heightPixels() const;
+
+    /**
+     * The shortest distance from the specified point to the plane in which this
+     * Screen lies.
+     *
+     * @returns The length of the perpendicular line segment extending from
+     * the plane this Screen lies in to the specified point.
+     * @since 1.0
+     */
+    LEAP_EXPORT float distanceToPoint(const Vector& point) const;
+
+    /**
+     * Reports whether this is a valid Screen object.
+     *
+     * **Important:** A valid Screen object does not necessarily contain
+     * up-to-date screen location information. Location information is only
+     * accurate until the Leap Motion Controller or the monitor are moved. In addition, the
+     * primary screen always contains default location information even if the
+     * user has never run the screen location utility. This default location
+     * information will not return accurate results.
+     *
+     * @returns True, if this Screen object contains valid data.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isValid() const;
+
+    /**
+     * Returns an invalid Screen object.
+     *
+     * You can use the instance returned by this function in comparisons testing
+     * whether a given Screen instance is valid or invalid. (You can also use the
+     * Screen::isValid() function.)
+     *
+     * @returns The invalid Screen instance.
+     * @since 1.0
+     */
+    LEAP_EXPORT static const Screen& invalid();
+
+    /**
+     * Compare Screen object equality.
+     * Two Screen objects are equal if and only if both Screen objects represent the
+     * exact same Screens and both Screens are valid.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator==(const Screen&) const;
+
+    /**
+     * Compare Screen object inequality.
+     * Two Screen objects are equal if and only if both Screen objects represent the
+     * exact same Screens and both Screens are valid.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator!=(const Screen&) const;
+
+    /**
+     * Writes a brief, human readable description of the Screen object.
+     * @since 1.0
+     */
+    LEAP_EXPORT friend std::ostream& operator<<(std::ostream&, const Screen&);
+
+    /**
+     * A string containing a brief, human readable description of the Screen object.
+     *
+     * @returns A description of the Screen as a string.
+     * @since 1.0
+     */
+    LEAP_EXPORT std::string toString() const;
+  };
+
+  /**
+   * The Device class represents a physically connected device.
+   *
+   * The Device class contains information related to a particular connected
+   * device such as field of view, device id, and calibrated positions.
+   *
+   * Note that Device objects can be invalid, which means that they do not contain
+   * valid device information and do not correspond to a physical device.
+   * Test for validity with the Device::isValid() function.
+   * @since 1.0
+   */
+  class Device : public Interface {
+  public:
+    // For internal use only.
+    Device(DeviceImplementation*);
+
+    /**
+     * Constructs a Device object.
+     *
+     * An uninitialized device is considered invalid.
+     * Get valid Device objects from a DeviceList object obtained using the
+     * Controller::devices() method.
+     *
+     * \include Device_Device.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT Device();
+
+    /**
+     * The angle of view along the x axis of this device.
+     *
+     * \image html images/Leap_horizontalViewAngle.png
+     *
+     * The Leap Motion controller scans a region in the shape of an inverted pyramid
+     * centered at the device's center and extending upwards. The horizontalViewAngle
+     * reports the view angle along the long dimension of the device.
+     *
+     * \include Device_horizontalViewAngle.txt
+     *
+     * @returns The horizontal angle of view in radians.
+     * @since 1.0
+     */
+    LEAP_EXPORT float horizontalViewAngle() const;
+
+    /**
+     * The angle of view along the z axis of this device.
+     *
+     * \image html images/Leap_verticalViewAngle.png
+     *
+     * The Leap Motion controller scans a region in the shape of an inverted pyramid
+     * centered at the device's center and extending upwards. The verticalViewAngle
+     * reports the view angle along the short dimension of the device.
+     *
+     * \include Device_verticalViewAngle.txt
+     *
+     * @returns The vertical angle of view in radians.
+     * @since 1.0
+     */
+    LEAP_EXPORT float verticalViewAngle() const;
+
+    /**
+     * The maximum reliable tracking range.
+     *
+     * The range reports the maximum recommended distance from the device center
+     * for which tracking is expected to be reliable. This distance is not a hard limit.
+     * Tracking may be still be functional above this distance or begin to degrade slightly
+     * before this distance depending on calibration and extreme environmental conditions.
+     *
+     * \include Device_range.txt
+     *
+     * @returns The recommended maximum range of the device in mm.
+     * @since 1.0
+     */
+    LEAP_EXPORT float range() const;
+
+    /**
+     * The distance to the nearest edge of the Leap Motion controller's view volume.
+     *
+     * The view volume is an axis-aligned, inverted pyramid centered on the device origin
+     * and extending upward to the range limit. The walls of the pyramid are described
+     * by the horizontalViewAngle and verticalViewAngle and the roof by the range.
+     * This function estimates the distance between the specified input position and the
+     * nearest wall or roof of the view volume.
+     *
+     * \include Device_distanceToBoundary.txt
+     *
+     * @param position The point to use for the distance calculation.
+     * @returns The distance in millimeters from the input position to the nearest boundary.
+     * @since 1.0
+     */
+    LEAP_EXPORT float distanceToBoundary(const Vector& position) const;
+
+    /**
+     * Reports whether this is a valid Device object.
+     *
+     * \include Device_isValid.txt
+     *
+     * @returns True, if this Device object contains valid data.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isValid() const;
+
+    /**
+     * Returns an invalid Device object.
+     *
+     * You can use the instance returned by this function in comparisons testing
+     * whether a given Device instance is valid or invalid. (You can also use the
+     * Device::isValid() function.)
+     *
+     * \include Device_invalid.txt
+     *
+     * @returns The invalid Device instance.
+     * @since 1.0
+     */
+    LEAP_EXPORT static const Device& invalid();
+
+    /**
+     * Compare Device object equality.
+     *
+     * \include Device_operator_equals.txt
+     *
+     * Two Device objects are equal if and only if both Device objects represent the
+     * exact same Device and both Devices are valid.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator==(const Device&) const;
+
+    /**
+     * Compare Device object inequality.
+     *
+     * \include Device_operator_not_equals.txt
+     *
+     * Two Device objects are equal if and only if both Device objects represent the
+     * exact same Device and both Devices are valid.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator!=(const Device&) const;
+
+    /**
+     * Writes a brief, human readable description of the Device object.
+     *
+     * \include Device_operator_stream.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT friend std::ostream& operator<<(std::ostream&, const Device&);
+
+    /**
+     * A string containing a brief, human readable description of the Device object.
+     *
+     * @returns A description of the Device as a string.
+     * @since 1.0
+     */
+    LEAP_EXPORT std::string toString() const;
+  };
+
+  // For internal use only.
+  template<typename L, typename T>
+  class ConstListIterator {
+  public:
+    ConstListIterator<L,T>(const L& list, int index) : m_list(list), m_index(index) {}
+
+    const T operator*() const { return m_list[m_index]; }
+    void operator++(int) {++m_index;}
+    const ConstListIterator<L,T>& operator++() { ++m_index; return *this; }
+    bool operator!=(const ConstListIterator<L,T>& rhs) const { return m_index != rhs.m_index; }
+    bool operator==(const ConstListIterator<L,T>& rhs) const { return m_index == rhs.m_index; }
+
+    typedef std::ptrdiff_t difference_type;
+    typedef T value_type;
+    typedef const T* pointer;
+    typedef const T& reference;
+    typedef std::forward_iterator_tag iterator_category;
+
+  private:
+    const L& m_list;
+    int m_index;
+  };
+
+  /**
+   * The PointableList class represents a list of Pointable objects.
+   *
+   * Pointable objects include entities that can be pointed, such as fingers and tools.
+   *
+   * Get a PointableList object by calling Frame::pointables() or Hand::pointables().
+   *
+   * \include PointableList_PointableList.txt
+   *
+   * @since 1.0
+   */
+  class PointableList : public Interface {
+  public:
+    // For internal use only.
+    PointableList(const ListBaseImplementation<Pointable>&);
+
+    /**
+     * Constructs an empty list of pointable entities.
+     * @since 1.0
+     */
+    LEAP_EXPORT PointableList();
+
+    /**
+     * Returns the number of pointable entities in this list.
+     *
+     * \include PointableList_count.txt
+     *
+     * @returns The number of pointable entities in this list.
+     * @since 1.0
+     */
+    LEAP_EXPORT int count() const;
+
+    /**
+     * Reports whether the list is empty.
+     *
+     * \include PointableList_isEmpty.txt
+     *
+     * @returns True, if the list has no members.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isEmpty() const;
+
+    /**
+     * Access a list member by its position in the list.
+     *
+     * \include PointableList_operator_index.txt
+     *
+     * @param index The zero-based list position index.
+     * @returns The Pointable object at the specified index.
+     * @since 1.0
+     */
+    LEAP_EXPORT Pointable operator[](int index) const;
+
+    /**
+     * Appends the members of the specifed PointableList to this PointableList.
+     * @param other A PointableList object containing Pointable objects
+     * to append to the end of this PointableList.
+     * @since 1.0
+     */
+    LEAP_EXPORT PointableList& append(const PointableList& other);
+
+    /**
+     * Appends the members of the specifed FingerList to this PointableList.
+     * @param other A FingerList object containing Finger objects
+     * to append to the end of this PointableList.
+     * @since 1.0
+     */
+    LEAP_EXPORT PointableList& append(const FingerList& other);
+
+    /**
+     * Appends the members of the specifed ToolList to this PointableList.
+     * @param other A ToolList object containing Tool objects
+     * to append to the end of this PointableList.
+     * @since 1.0
+     */
+    LEAP_EXPORT PointableList& append(const ToolList& other);
+
+    /**
+     * The member of the list that is farthest to the left within the standard
+     * Leap Motion frame of reference (i.e has the smallest X coordinate).
+     *
+     * \include PointableList_leftmost.txt
+     *
+     * @returns The leftmost pointable, or invalid if list is empty.
+     * @since 1.0
+     */
+    LEAP_EXPORT Pointable leftmost() const;
+
+    /**
+     * The member of the list that is farthest to the right within the standard
+     * Leap Motion frame of reference (i.e has the largest X coordinate).
+     *
+     * \include PointableList_rightmost.txt
+     *
+     * @returns The rightmost pointable, or invalid if list is empty.
+     * @since 1.0
+     */
+    LEAP_EXPORT Pointable rightmost() const;
+
+
+    /**
+     * The member of the list that is farthest to the front within the standard
+     * Leap Motion frame of reference (i.e has the smallest Z coordinate).
+     *
+     * \include PointableList_frontmost.txt
+     *
+     * @returns The frontmost pointable, or invalid if list is empty.
+     * @since 1.0
+     */
+    LEAP_EXPORT Pointable frontmost() const;
+
+    /**
+     * A C++ iterator type for PointableList objects.
+     *
+     * \include PointableList_iterator.txt
+     *
+     * @since 1.0
+     */
+    typedef ConstListIterator<PointableList, Pointable> const_iterator;
+
+    /**
+     * The C++ iterator set to the beginning of this PointableList.
+     *
+     * \include PointableList_begin.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator begin() const;
+
+    /**
+     * The C++ iterator set to the end of this PointableList.
+     *
+     * \include PointableList_end.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator end() const;
+  };
+
+  /**
+   * The FingerList class represents a list of Finger objects.
+   *
+   * Get a FingerList object by calling Frame::fingers().
+   *
+   * \include FingerList_FingerList.txt
+   *
+   * @since 1.0
+   */
+  class FingerList : public Interface {
+  public:
+    // For internal use only.
+    FingerList(const ListBaseImplementation<Finger>&);
+
+    /**
+     * Constructs an empty list of fingers.
+     * @since 1.0
+     */
+    LEAP_EXPORT FingerList();
+
+    /**
+     * Returns the number of fingers in this list.
+     *
+     * \include FingerList_count.txt
+     *
+     * @returns The number of fingers in this list.
+     * @since 1.0
+     */
+    LEAP_EXPORT int count() const;
+
+    /**
+     * Reports whether the list is empty.
+     *
+     * \include FingerList_isEmpty.txt
+     *
+     * @returns True, if the list has no members.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isEmpty() const;
+
+    /**
+     * Access a list member by its position in the list.
+     *
+     * \include FingerList_index.txt
+     *
+     * @param index The zero-based list position index.
+     * @returns The Finger object at the specified index.
+     * @since 1.0
+     */
+    LEAP_EXPORT Finger operator[](int index) const;
+
+    /**
+     * Appends the members of the specifed FingerList to this FingerList.
+     * @param other A FingerList object containing Finger objects
+     * to append to the end of this FingerList.
+     * @since 1.0
+     */
+    LEAP_EXPORT FingerList& append(const FingerList& other);
+
+    /**
+     * The member of the list that is farthest to the left within the standard
+     * Leap Motion frame of reference (i.e has the smallest X coordinate).
+     *
+     * \include FingerList_leftmost.txt
+     *
+     * @returns The leftmost finger, or invalid if list is empty.
+     * @since 1.0
+     */
+    LEAP_EXPORT Finger leftmost() const;
+
+    /**
+     * The member of the list that is farthest to the right within the standard
+     * Leap Motion frame of reference (i.e has the largest X coordinate).
+     *
+     * \include FingerList_rightmost.txt
+     *
+     * @returns The rightmost finger, or invalid if list is empty.
+     * @since 1.0
+     */
+    LEAP_EXPORT Finger rightmost() const;
+
+    /**
+     * The member of the list that is farthest to the front within the standard
+     * Leap Motion frame of reference (i.e has the smallest Z coordinate).
+     *
+     * \include FingerList_frontmost.txt
+     *
+     * @returns The frontmost finger, or invalid if list is empty.
+     * @since 1.0
+     */
+    LEAP_EXPORT Finger frontmost() const;
+
+    /**
+     * A C++ iterator type for FingerList objects.
+     *
+     * \include FingerList_iterator.txt
+     *
+     * @since 1.0
+     */
+    typedef ConstListIterator<FingerList, Finger> const_iterator;
+
+    /**
+     * The C++ iterator set to the beginning of this FingerList.
+     *
+     * \include FingerList_begin.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator begin() const;
+
+    /**
+     * The C++ iterator set to the end of this FingerList.
+     *
+     * \include FingerList_end.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator end() const;
+  };
+
+  /**
+   * The ToolList class represents a list of Tool objects.
+   *
+   * Get a ToolList object by calling Frame::tools() or Hand::tools().
+   *
+   * \include ToolList_ToolList.txt
+   *
+   * @since 1.0
+   */
+  class ToolList : public Interface {
+  public:
+    // For internal use only.
+    ToolList(const ListBaseImplementation<Tool>&);
+
+    /**
+     * Constructs an empty list of tools.
+     * @since 1.0
+     */
+    LEAP_EXPORT ToolList();
+
+    /**
+     * Returns the number of tools in this list.
+     *
+     * \include ToolList_count.txt
+     *
+     * @returns The number of tools in this list.
+     * @since 1.0
+     */
+    LEAP_EXPORT int count() const;
+
+    /**
+     * Reports whether the list is empty.
+     *
+     * \include ToolList_isEmpty.txt
+     *
+     * @returns True, if the list has no members.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isEmpty() const;
+
+    /**
+     * Access a list member by its position in the list.
+     *
+     * \include ToolList_operator_index.txt
+     *
+     * @param index The zero-based list position index.
+     * @returns The Tool object at the specified index.
+     * @since 1.0
+     */
+    LEAP_EXPORT Tool operator[](int index) const;
+
+    /**
+     * Appends the members of the specifed ToolList to this ToolList.
+     * @param other A ToolList object containing Tool objects
+     * to append to the end of this ToolList.
+     * @since 1.0
+     */
+    LEAP_EXPORT ToolList& append(const ToolList& other);
+
+    /**
+     * The member of the list that is farthest to the left within the standard
+     * Leap Motion frame of reference (i.e has the smallest X coordinate).
+     *
+     * \include ToolList_leftmost.txt
+     *
+     * @returns The leftmost tool, or invalid if list is empty.
+     * @since 1.0
+     */
+    LEAP_EXPORT Tool leftmost() const;
+
+    /**
+     * The member of the list that is farthest to the right within the standard
+     * Leap Motion frame of reference (i.e has the largest X coordinate).
+     *
+     * \include ToolList_rightmost.txt
+     *
+     * @returns The rightmost tool, or invalid if list is empty.
+     * @since 1.0
+     */
+    LEAP_EXPORT Tool rightmost() const;
+
+    /**
+     * The member of the list that is farthest to the front within the standard
+     * Leap Motion frame of reference (i.e has the smallest Z coordinate).
+     *
+     * \include ToolList_frontmost.txt
+     *
+     * @returns The frontmost tool, or invalid if list is empty.
+     * @since 1.0
+     */
+    LEAP_EXPORT Tool frontmost() const;
+
+    /**
+     * A C++ iterator type for ToolList objects.
+     *
+     * \include ToolList_iterator.txt
+     *
+     * @since 1.0
+     */
+    typedef ConstListIterator<ToolList, Tool> const_iterator;
+
+    /**
+     * The C++ iterator set to the beginning of this ToolList.
+     *
+     * \include ToolList_begin.txt
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator begin() const;
+
+    /**
+     * The C++ iterator set to the end of this ToolList.
+     *
+     * \include ToolList_end.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator end() const;
+  };
+
+  /**
+   * The HandList class represents a list of Hand objects.
+   *
+   * Get a HandList object by calling Frame::hands().
+   *
+   * \include HandList_HandList.txt
+   *
+   * @since 1.0
+   */
+  class HandList : public Interface {
+  public:
+    // For internal use only.
+    HandList(const ListBaseImplementation<Hand>&);
+
+    /**
+     * Constructs an empty list of hands.
+     * @since 1.0
+     */
+    LEAP_EXPORT HandList();
+
+    /**
+     * Returns the number of hands in this list.
+     *
+     * \include HandList_count.txt
+     * @returns The number of hands in this list.
+     * @since 1.0
+     */
+    LEAP_EXPORT int count() const;
+
+    /**
+     * Reports whether the list is empty.
+     *
+     * \include HandList_isEmpty.txt
+     *
+     * @returns True, if the list has no members.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isEmpty() const;
+
+    /**
+     * Access a list member by its position in the list.
+     *
+     * \include HandList_operator_index.txt
+     *
+     * @param index The zero-based list position index.
+     * @returns The Hand object at the specified index.
+     * @since 1.0
+     */
+    LEAP_EXPORT Hand operator[](int index) const;
+
+    /**
+     * Appends the members of the specifed HandList to this HandList.
+     * @param other A HandList object containing Hand objects
+     * to append to the end of this HandList.
+     */
+    LEAP_EXPORT HandList& append(const HandList& other);
+
+    /**
+     * The member of the list that is farthest to the left within the standard
+     * Leap Motion frame of reference (i.e has the smallest X coordinate).
+     *
+     * \include HandList_leftmost.txt
+     *
+     * @returns The leftmost hand, or invalid if list is empty.
+     * @since 1.0
+     */
+    LEAP_EXPORT Hand leftmost() const;
+
+    /**
+     * The member of the list that is farthest to the right within the standard
+     * Leap Motion frame of reference (i.e has the largest X coordinate).
+     *
+     * \include HandList_rightmost.txt
+     *
+     * @returns The rightmost hand, or invalid if list is empty.
+     * @since 1.0
+     */
+    LEAP_EXPORT Hand rightmost() const;
+
+    /**
+     * The member of the list that is farthest to the front within the standard
+     * Leap Motion frame of reference (i.e has the smallest Z coordinate).
+     *
+     * \include HandList_frontmost.txt
+     *
+     * @returns The frontmost hand, or invalid if list is empty.
+     * @since 1.0
+     */
+    LEAP_EXPORT Hand frontmost() const;
+
+    /**
+     * A C++ iterator type for this HandList objects.
+     *
+     * \include HandList_iterator.txt
+     *
+     * @since 1.0
+     */
+    typedef ConstListIterator<HandList, Hand> const_iterator;
+
+    /**
+     * The C++ iterator set to the beginning of this HandList.
+     *
+     * \include HandList_begin.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator begin() const;
+
+    /**
+     * The C++ iterator set to the end of this HandList.
+     *
+     * \include HandList_end.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator end() const;
+  };
+
+  /**
+   * The GestureList class represents a list of Gesture objects.
+   *
+   * Get a GestureList object from a Frame object.
+   * @since 1.0
+   */
+  class GestureList : public Interface {
+  public:
+    // For internal use only.
+    GestureList(const ListBaseImplementation<Gesture>&);
+
+    /**
+     * Constructs an empty gesture list.
+     * @since 1.0
+     */
+    LEAP_EXPORT GestureList();
+
+    /**
+     * The length of this list.
+     *
+     * \include GestureList_count.txt
+     *
+     * @returns The number of gestures in this list.
+     * @since 1.0
+     */
+    LEAP_EXPORT int count() const;
+
+    /**
+     * Reports whether the list is empty.
+     *
+     * \include GestureList_isEmpty.txt
+     *
+     * @returns True, if the list has no members.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isEmpty() const;
+
+    /**
+     * Access a list member by its position in the list.
+     *
+     * \include GestureList_operator_index.txt
+     *
+     * @param index The zero-based list position index.
+     * @returns The Gesture object at the specified index.
+     * @since 1.0
+     */
+    LEAP_EXPORT Gesture operator[](int index) const;
+
+    /**
+     * Appends the members of the specified GestureList to this GestureList.
+     * @param other A GestureList object containing Gesture objects
+     * to append to the end of this GestureList.
+     * @since 1.0
+     */
+    LEAP_EXPORT GestureList& append(const GestureList& other);
+
+    /**
+     * A C++ iterator type for GestureList objects.
+     *
+     * \include GestureList_iterator.txt
+     * @since 1.0
+     */
+    typedef ConstListIterator<GestureList, Gesture> const_iterator;
+
+    /**
+     * The C++ iterator set to the beginning of this GestureList.
+     *
+     * \include GestureList_begin.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator begin() const;
+
+    /**
+     * The C++ iterator set to the end of this GestureList.
+     *
+     * \include GestureList_end.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator end() const;
+  };
+
+  /*
+   * The ScreenList and Screen classes are currently unsupported.
+   *
+   * We are re-evaluating this feature due to the cumbersome location process
+   * required to use it and the amount of confusion about the feature's purpose.
+   *
+   * The ScreenList class represents a list of Screen objects.
+   *
+   * The list always contains at least one entry representing the default
+   * screen. If the user has not registered the location of this default
+   * screen, then the coordinates, directions, and other values reported by
+   * the functions in its Screen object will not be accurate. Other monitor
+   * screens only appear in the list if their positions have been registered
+   * using the Leap Motion Screen Locator.
+   *
+   * Get a ScreenList object by calling Controller::locatedScreens().
+   *
+   * \include Screen_Closest_1.txt
+   * @since 1.0
+   */
+  class ScreenList : public Interface {
+  public:
+    // For internal use only.
+    ScreenList(const ListBaseImplementation<Screen>&);
+
+    /**
+     * Constructs an empty list of screens.
+     * @since 1.0
+     */
+    LEAP_EXPORT ScreenList();
+
+    /**
+     * Returns the number of screens in this list.
+     * @returns The number of screens in this list.
+     * @since 1.0
+     */
+    LEAP_EXPORT int count() const;
+
+    /**
+     * Reports whether the list is empty.
+     * @returns True, if the list has no members.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isEmpty() const;
+
+    /**
+     * Access a list member by its position in the list.
+     * @param index The zero-based list position index.
+     * @returns The Screen object at the specified index.
+     * @since 1.0
+     */
+    LEAP_EXPORT Screen operator[](int index) const;
+
+    /**
+     * A C++ iterator type for this ScreenList objects.
+     * @since 1.0
+     */
+    typedef ConstListIterator<ScreenList, Screen> const_iterator;
+
+    /**
+     * The C++ iterator set to the beginning of this ScreenList.
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator begin() const;
+
+    /**
+     * The C++ iterator set to the end of this ScreenList.
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator end() const;
+
+    /**
+     * Gets the closest Screen intercepting a ray projecting from the specified
+     * Pointable object.
+     *
+     * The projected ray emanates from the Pointable tipPosition along the
+     * Pointable's direction vector. If the projected ray does not intersect
+     * any screen surface directly, then the Leap Motion software checks for intersection with
+     * the planes extending from the surfaces of the known screens
+     * and returns the Screen with the closest intersection.
+     *
+     * \include Screen_Closest_2.txt
+     *
+     * If no intersections are found (i.e. the ray is directed parallel to or
+     * away from all known screens), then an invalid Screen object is returned.
+     *
+     * *Note:* Be sure to test whether the Screen object returned by this method
+     * is valid. Attempting to use an invalid Screen object will lead to
+     * incorrect results.
+     *
+     * @param pointable The Pointable object to check for screen intersection.
+     * @returns The closest Screen toward which the specified Pointable object
+     * is pointing, or, if the pointable is not pointing in the direction of
+     * any known screen, an invalid Screen object.
+     * @since 1.0
+     */
+    LEAP_EXPORT Screen closestScreenHit(const Pointable& pointable) const;
+
+    /**
+     * Gets the closest Screen intercepting a ray projecting from the specified
+     * position in the specified direction.
+     *
+     * The projected ray emanates from the position along the direction vector.
+     * If the projected ray does not intersect any screen surface directly,
+     * then the Leap Motion software checks for intersection with the planes extending from the
+     * surfaces of the known screens and returns the Screen with the closest
+     * intersection.
+     *
+     * \include Screen_Closest_3.txt
+     *
+     * If no intersections are found (i.e. the ray is directed parallel to or
+     * away from all known screens), then an invalid Screen object is returned.
+     *
+     * *Note:* Be sure to test whether the Screen object returned by this method
+     * is valid. Attempting to use an invalid Screen object will lead to
+     * incorrect results.
+     *
+     * @param position The position from which to check for screen intersection.
+     * @param direction The direction in which to check for screen intersection.
+     * @returns The closest Screen toward which the specified ray is pointing,
+     * or, if the ray is not pointing in the direction of any known screen,
+     * an invalid Screen object.
+     * @since 1.0
+     */
+    LEAP_EXPORT Screen closestScreenHit(const Vector& position, const Vector& direction) const;
+
+    /**
+     * Gets the Screen closest to the specified position.
+     *
+     * The specified position is projected along each screen's normal vector
+     * onto the screen's plane. The screen whose projected point is closest to
+     * the specified position is returned. Call Screen::project(position)
+     * on the returned Screen object to find the projected point.
+     *
+     * \include Screen_Closest_3.txt
+     *
+     * @param position The position from which to check for screen projection.
+     * @returns The closest Screen onto which the specified position is projected.
+     * @since 1.0
+     */
+    LEAP_EXPORT Screen closestScreen(const Vector& position) const;
+  };
+
+  /**
+   * The DeviceList class represents a list of Device objects.
+   *
+   * Get a DeviceList object by calling Controller::devices().
+   * @since 1.0
+   */
+  class DeviceList : public Interface {
+  public:
+    // For internal use only.
+    DeviceList(const ListBaseImplementation<Device>&);
+
+    /**
+     * Constructs an empty list of devices.
+     * @since 1.0
+     */
+    LEAP_EXPORT DeviceList();
+
+    /**
+     * Returns the number of devices in this list.
+     * @returns The number of devices in this list.
+     * @since 1.0
+     */
+    LEAP_EXPORT int count() const;
+
+    /**
+     * Reports whether the list is empty.
+     *
+     * \include DeviceList_isEmpty.txt
+     *
+     * @returns True, if the list has no members.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isEmpty() const;
+
+    /**
+     * Access a list member by its position in the list.
+     * @param index The zero-based list position index.
+     * @returns The Device object at the specified index.
+     * @since 1.0
+     */
+    LEAP_EXPORT Device operator[](int index) const;
+
+    /**
+     * Appends the members of the specifed DeviceList to this DeviceList.
+     * @param other A DeviceList object containing Device objects
+     * to append to the end of this DeviceList.
+     * @since 1.0
+     */
+    LEAP_EXPORT DeviceList& append(const DeviceList& other);
+
+    /**
+     * A C++ iterator type for this DeviceList objects.
+     * @since 1.0
+     */
+    typedef ConstListIterator<DeviceList, Device> const_iterator;
+
+    /**
+     * The C++ iterator set to the beginning of this DeviceList.
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator begin() const;
+
+    /**
+     * The C++ iterator set to the end of this DeviceList.
+     * @since 1.0
+     */
+    LEAP_EXPORT const_iterator end() const;
+  };
+
+  /**
+   * The InteractionBox class represents a box-shaped region completely
+   * within the field of view of the Leap Motion controller.
+   *
+   * The interaction box is an axis-aligned rectangular prism and provides normalized
+   * coordinates for hands, fingers, and tools within this box. The InteractionBox class
+   * can make it easier to map positions in the Leap Motion coordinate system to 2D or
+   * 3D coordinate systems used for application drawing.
+   *
+   * \image html images/Leap_InteractionBox.png
+   *
+   * The InteractionBox region is defined by a center and dimensions along the x, y,
+   * and z axes.
+   *
+   * Get an InteractionBox object from a Frame object.
+   * @since 1.0
+   */
+  class InteractionBox : public Interface {
+  public:
+    // For internal use only.
+    InteractionBox(InteractionBoxImplementation*);
+
+    LEAP_EXPORT InteractionBox();
+
+    /**
+     * Normalizes the coordinates of a point using the interaction box.
+     *
+     * \include InteractionBox_normalizePoint.txt
+     *
+     * Coordinates from the Leap Motion frame of reference (millimeters) are converted
+     * to a range of [0..1] such that the minimum value of the InteractionBox maps to 0
+     * and the maximum value of the InteractionBox maps to 1.
+     *
+     * @param position The input position in device coordinates.
+     * @param clamp Whether or not to limit the output value to the range [0,1] when the
+     * input position is outside the InteractionBox. Defaults to true.
+     * @returns The normalized position.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector normalizePoint(const Vector& position, bool clamp = true) const;
+
+    /**
+     * Converts a position defined by normalized InteractionBox coordinates into device
+     * coordinates in millimeters.
+     *
+     * \include InteractionBox_denormalizePoint.txt
+     *
+     * This function performs the inverse of normalizePoint().
+     *
+     * @param normalizedPosition The input position in InteractionBox coordinates.
+     * @returns The corresponding denormalized position in device coordinates.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector denormalizePoint(const Vector& normalizedPosition) const;
+
+    /**
+     * The center of the InteractionBox in device coordinates (millimeters). This point
+     * is equidistant from all sides of the box.
+     *
+     * \include InteractionBox_center.txt
+     *
+     * @returns The InteractionBox center in device coordinates.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector center() const;
+
+    /**
+     * The width of the InteractionBox in millimeters, measured along the x-axis.
+     *
+     * \include InteractionBox_width.txt
+     *
+     * @returns The InteractionBox width in millimeters.
+     * @since 1.0
+     */
+    LEAP_EXPORT float width() const;
+
+    /**
+     * The height of the InteractionBox in millimeters, measured along the y-axis.
+     *
+     * \include InteractionBox_height.txt
+     *
+     * @returns The InteractionBox height in millimeters.
+     * @since 1.0
+     */
+    LEAP_EXPORT float height() const;
+
+    /**
+     * The depth of the InteractionBox in millimeters, measured along the z-axis.
+     *
+     * \include InteractionBox_depth.txt
+     *
+     * @returns The InteractionBox depth in millimeters.
+     * @since 1.0
+     */
+    LEAP_EXPORT float depth() const;
+
+    /**
+     * Reports whether this is a valid InteractionBox object.
+     *
+     * \include InteractionBox_isValid.txt
+     *
+     * @returns True, if this InteractionBox object contains valid data.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isValid() const;
+
+    /**
+     * Returns an invalid InteractionBox object.
+     *
+     * You can use the instance returned by this function in comparisons testing
+     * whether a given InteractionBox instance is valid or invalid. (You can also use the
+     * InteractionBox::isValid() function.)
+     *
+     * \include InteractionBox_invalid.txt
+     *
+     * @returns The invalid InteractionBox instance.
+     * @since 1.0
+     */
+    LEAP_EXPORT static const InteractionBox& invalid();
+
+    /**
+     * Compare InteractionBox object equality.
+     *
+     * \include InteractionBox_operator_equals.txt
+     *
+     * Two InteractionBox objects are equal if and only if both InteractionBox objects represent the
+     * exact same InteractionBox and both InteractionBoxes are valid.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator==(const InteractionBox&) const;
+
+    /**
+     * Compare InteractionBox object inequality.
+     *
+     * \include InteractionBox_operator_not_equals.txt
+     *
+     * Two InteractionBox objects are equal if and only if both InteractionBox objects represent the
+     * exact same InteractionBox and both InteractionBoxes are valid.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator!=(const InteractionBox&) const;
+
+    /**
+     * Writes a brief, human readable description of the InteractionBox object.
+     *
+     * \include InteractionBox_operator_stream.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT friend std::ostream& operator<<(std::ostream&, const InteractionBox&);
+
+    /**
+     * A string containing a brief, human readable description of the InteractionBox object.
+     *
+     * @returns A description of the InteractionBox as a string.
+     * @since 1.0
+     */
+    LEAP_EXPORT std::string toString() const;
+  };
+
+  /**
+   * The Frame class represents a set of hand and finger tracking data detected
+   * in a single frame.
+   *
+   * The Leap Motion software detects hands, fingers and tools within the tracking area, reporting
+   * their positions, orientations, gestures, and motions in frames at the Leap Motion frame rate.
+   *
+   * Access Frame objects through an instance of the Controller class: 
+   *
+   * \include Controller_Frame_1.txt
+   *
+   * Implement a Listener subclass to receive a callback event when a new Frame is available.
+   * @since 1.0
+   */
+  class Frame : public Interface {
+  public:
+    // For internal use only.
+    Frame(FrameImplementation*);
+
+    /**
+     * Constructs a Frame object.
+     *
+     * Frame instances created with this constructor are invalid.
+     * Get valid Frame objects by calling the Controller::frame() function.
+     *
+     * \include Frame_Frame.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT Frame();
+
+    /**
+     * A unique ID for this Frame. 
+     *
+     * Consecutive frames processed by the Leap Motion software have consecutive 
+     * increasing values. You can use the frame ID to avoid processing the same
+     * Frame object twice:
+     *
+     * \include Frame_Duplicate.txt
+     *
+     * As well as to make sure that your application processes every frame:
+     *
+     * \include Frame_Skipped.txt
+     *
+     * @returns The frame ID.
+     * @since 1.0
+     */
+    LEAP_EXPORT int64_t id() const;
+
+    /**
+     * The frame capture time in microseconds elapsed since the Leap started.
+     *
+     * \include Frame_timestamp.txt
+     *
+     * @returns The timestamp in microseconds.
+     * @since 1.0
+     */
+    LEAP_EXPORT int64_t timestamp() const;
+
+    /**
+     * The list of Hand objects detected in this frame, given in arbitrary order.
+     * The list can be empty if no hands are detected.
+     *
+     * \include Frame_hands.txt
+     *
+     * @returns The HandList containing all Hand objects detected in this frame.
+     * @since 1.0
+     */
+    LEAP_EXPORT HandList hands() const;
+
+    /**
+     * The Hand object with the specified ID in this frame.
+     *
+     * Use the Frame::hand() function to retrieve the Hand object from
+     * this frame using an ID value obtained from a previous frame.
+     * This function always returns a Hand object, but if no hand
+     * with the specified ID is present, an invalid Hand object is returned.
+     *
+     * \include Frame_hand.txt
+     *
+     * Note that ID values persist across frames, but only until tracking of a
+     * particular object is lost. If tracking of a hand is lost and subsequently
+     * regained, the new Hand object representing that physical hand may have
+     * a different ID than that representing the physical hand in an earlier frame.
+     *
+     * @param id The ID value of a Hand object from a previous frame.
+     * @returns The Hand object with the matching ID if one exists in this frame;
+     * otherwise, an invalid Hand object is returned.
+     * @since 1.0
+     */
+    LEAP_EXPORT Hand hand(int32_t id) const;
+
+    /**
+     * The list of Pointable objects (fingers and tools) detected in this frame,
+     * given in arbitrary order. The list can be empty if no fingers or tools are detected.
+     *
+     * \include Frame_pointables.txt
+     *
+     * @returns The PointableList containing all Pointable objects detected in this frame.
+     * @since 1.0
+     */
+    LEAP_EXPORT PointableList pointables() const;
+
+    /**
+     * The Pointable object with the specified ID in this frame.
+     *
+     * Use the Frame::pointable() function to retrieve the Pointable object from
+     * this frame using an ID value obtained from a previous frame.
+     * This function always returns a Pointable object, but if no finger or tool
+     * with the specified ID is present, an invalid Pointable object is returned.
+     *
+     * \include Frame_pointable.txt
+     *
+     * Note that ID values persist across frames, but only until tracking of a
+     * particular object is lost. If tracking of a finger or tool is lost and subsequently
+     * regained, the new Pointable object representing that finger or tool may have
+     * a different ID than that representing the finger or tool in an earlier frame.
+     *
+     * @param id The ID value of a Pointable object from a previous frame.
+     * @returns The Pointable object with the matching ID if one exists in this frame;
+     * otherwise, an invalid Pointable object is returned.
+     * @since 1.0
+     */
+    LEAP_EXPORT Pointable pointable(int32_t id) const;
+
+    /**
+     * The list of Finger objects detected in this frame, given in arbitrary order.
+     * The list can be empty if no fingers are detected.
+     *
+     * \include Frame_fingers.txt
+     *
+     * @returns The FingerList containing all Finger objects detected in this frame.
+     * @since 1.0
+     */
+    LEAP_EXPORT FingerList fingers() const;
+
+    /**
+     * The Finger object with the specified ID in this frame.
+     *
+     * Use the Frame::finger() function to retrieve the Finger object from
+     * this frame using an ID value obtained from a previous frame.
+     * This function always returns a Finger object, but if no finger
+     * with the specified ID is present, an invalid Finger object is returned.
+     *
+     * \include Frame_finger.txt
+     *
+     * Note that ID values persist across frames, but only until tracking of a
+     * particular object is lost. If tracking of a finger is lost and subsequently
+     * regained, the new Finger object representing that physical finger may have
+     * a different ID than that representing the finger in an earlier frame.
+     *
+     * @param id The ID value of a Finger object from a previous frame.
+     * @returns The Finger object with the matching ID if one exists in this frame;
+     * otherwise, an invalid Finger object is returned.
+     * @since 1.0
+     */
+    LEAP_EXPORT Finger finger(int32_t id) const;
+
+    /**
+     * The list of Tool objects detected in this frame, given in arbitrary order.
+     * The list can be empty if no tools are detected.
+     *
+     * \include Frame_tools.txt
+     *
+     * @returns The ToolList containing all Tool objects detected in this frame.
+     * @since 1.0
+     */
+    LEAP_EXPORT ToolList tools() const;
+
+    /**
+     * The Tool object with the specified ID in this frame.
+     *
+     * Use the Frame::tool() function to retrieve the Tool object from
+     * this frame using an ID value obtained from a previous frame.
+     * This function always returns a Tool object, but if no tool
+     * with the specified ID is present, an invalid Tool object is returned.
+     *
+     * \include Frame_tool.txt
+     *
+     * Note that ID values persist across frames, but only until tracking of a
+     * particular object is lost. If tracking of a tool is lost and subsequently
+     * regained, the new Tool object representing that tool may have a
+     * different ID than that representing the tool in an earlier frame.
+     *
+     * @param id The ID value of a Tool object from a previous frame.
+     * @returns The Tool object with the matching ID if one exists in this frame;
+     * otherwise, an invalid Tool object is returned.
+     * @since 1.0
+     */
+    LEAP_EXPORT Tool tool(int32_t id) const;
+
+    /**
+     * The Gesture object with the specified ID in this frame.
+     *
+     * Use the Frame::gesture() function to return a Gesture object in this
+     * frame using an ID obtained in an earlier frame. The function always
+     * returns a Gesture object, but if there was no update for the gesture in
+     * this frame, then an invalid Gesture object is returned.
+     *
+     * \include Frame_gesture.txt
+     *
+     * All Gesture objects representing the same recognized movement share the
+     * same ID.
+     * @param id The ID of an Gesture object from a previous frame.
+     * @returns The Gesture object in the frame with the specified ID if one
+     * exists; Otherwise, an Invalid Gesture object.
+     * @since 1.0
+     */
+    LEAP_EXPORT Gesture gesture(int32_t id) const;
+
+    /**
+     * The gestures recognized or continuing in this frame.
+     *
+     * \include Frame_gestures_now.txt
+     *
+     * Circle and swipe gestures are updated every frame. Tap gestures
+     * only appear in the list  for a single frame.
+     *
+     * @return GestureList the list of gestures.
+     * @since 1.0
+     */
+    LEAP_EXPORT GestureList gestures() const;
+
+    /**
+     * Returns a GestureList containing all gestures that have occured since
+     * the specified frame.
+     *
+     * \include Frame_gestures_since.txt
+     *
+     * @param sinceFrame An earlier Frame object. The starting frame must
+     * still be in the frame history cache, which has a default length of
+     * 60 frames.
+     * @return GestureList The list of the Gesture objects that have occured
+     * since the specified frame.
+     * @since 1.0
+     */
+    LEAP_EXPORT GestureList gestures(const Frame& sinceFrame) const;
+
+    /**
+     * The change of position derived from the overall linear motion between
+     * the current frame and the specified frame.
+     *
+     * The returned translation vector provides the magnitude and direction of
+     * the movement in millimeters.
+     *
+     * \include Frame_translation.txt
+     *
+     * The Leap Motion software derives frame translation from the linear motion of
+     * all objects detected in the field of view.
+     *
+     * If either this frame or sinceFrame is an invalid Frame object, then this
+     * method returns a zero vector.
+     *
+     * @param sinceFrame The starting frame for computing the relative translation.
+     * @returns A Vector representing the heuristically determined change in
+     * position of all objects between the current frame and that specified
+     * in the sinceFrame parameter.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector translation(const Frame& sinceFrame) const;
+
+    /**
+     * The estimated probability that the overall motion between the current
+     * frame and the specified frame is intended to be a translating motion.
+     *
+     * \include Frame_translationProbability.txt
+     *
+     * If either this frame or sinceFrame is an invalid Frame object, then this
+     * method returns zero.
+     *
+     * @param sinceFrame The starting frame for computing the translation.
+     * @returns A value between 0 and 1 representing the estimated probability
+     * that the overall motion between the current frame and the specified frame
+     * is intended to be a translating motion.
+     * @since 1.0
+     */
+    LEAP_EXPORT float translationProbability(const Frame& sinceFrame) const;
+
+    /**
+     * The axis of rotation derived from the overall rotational motion between
+     * the current frame and the specified frame.
+     *
+     * The returned direction vector is normalized.
+     *
+     * \include Frame_rotationAxis.txt
+     *
+     * The Leap Motion software derives frame rotation from the relative change in position and
+     * orientation of all objects detected in the field of view.
+     *
+     * If either this frame or sinceFrame is an invalid Frame object, or if no
+     * rotation is detected between the two frames, a zero vector is returned.
+     *
+     * @param sinceFrame The starting frame for computing the relative rotation.
+     * @returns A normalized direction Vector representing the axis of the
+     * heuristically determined rotational change between the current frame
+     * and that specified in the sinceFrame parameter.
+     * @since 1.0
+     */
+    LEAP_EXPORT Vector rotationAxis(const Frame& sinceFrame) const;
+
+    /**
+     * The angle of rotation around the rotation axis derived from the overall
+     * rotational motion between the current frame and the specified frame.
+     *
+     * The returned angle is expressed in radians measured clockwise around the
+     * rotation axis (using the right-hand rule) between the start and end frames.
+     * The value is always between 0 and pi radians (0 and 180 degrees).
+     *
+     * \include Frame_rotationAngle.txt
+     *
+     * The Leap Motion software derives frame rotation from the relative change in position and
+     * orientation of all objects detected in the field of view.
+     *
+     * If either this frame or sinceFrame is an invalid Frame object, then the
+     * angle of rotation is zero.
+     *
+     * @param sinceFrame The starting frame for computing the relative rotation.
+     * @returns A positive value containing the heuristically determined
+     * rotational change between the current frame and that specified in the
+     * sinceFrame parameter.
+     * @since 1.0
+     */
+    LEAP_EXPORT float rotationAngle(const Frame& sinceFrame) const;
+
+    /**
+     * The angle of rotation around the specified axis derived from the overall
+     * rotational motion between the current frame and the specified frame.
+     *
+     * The returned angle is expressed in radians measured clockwise around the
+     * rotation axis (using the right-hand rule) between the start and end frames.
+     * The value is always between -pi and pi radians (-180 and 180 degrees).
+     *
+     * \include Frame_rotationAngle_axis.txt
+     *
+     * The Leap Motion software derives frame rotation from the relative change in position and
+     * orientation of all objects detected in the field of view.
+     *
+     * If either this frame or sinceFrame is an invalid Frame object, then the
+     * angle of rotation is zero.
+     *
+     * @param sinceFrame The starting frame for computing the relative rotation.
+     * @param axis The axis to measure rotation around.
+     * @returns A value containing the heuristically determined rotational
+     * change between the current frame and that specified in the sinceFrame
+     * parameter around the given axis.
+     * @since 1.0
+     */
+    LEAP_EXPORT float rotationAngle(const Frame& sinceFrame, const Vector& axis) const;
+
+    /**
+     * The transform matrix expressing the rotation derived from the overall
+     * rotational motion between the current frame and the specified frame.
+     *
+     * \include Frame_rotationMatrix.txt
+     *
+     * The Leap Motion software derives frame rotation from the relative change in position and
+     * orientation of all objects detected in the field of view.
+     *
+     * If either this frame or sinceFrame is an invalid Frame object, then this
+     * method returns an identity matrix.
+     *
+     * @param sinceFrame The starting frame for computing the relative rotation.
+     * @returns A transformation Matrix containing the heuristically determined
+     * rotational change between the current frame and that specified in the
+     * sinceFrame parameter.
+     * @since 1.0
+     */
+    LEAP_EXPORT Matrix rotationMatrix(const Frame& sinceFrame) const;
+
+    /**
+     * The estimated probability that the overall motion between the current
+     * frame and the specified frame is intended to be a rotating motion.
+     *
+     * \include Frame_rotationProbability.txt
+     *
+     * If either this frame or sinceFrame is an invalid Frame object, then this
+     * method returns zero.
+     *
+     * @param sinceFrame The starting frame for computing the relative rotation.
+     * @returns A value between 0 and 1 representing the estimated probability
+     * that the overall motion between the current frame and the specified frame
+     * is intended to be a rotating motion.
+     * @since 1.0
+     */
+    LEAP_EXPORT float rotationProbability(const Frame& sinceFrame) const;
+
+    /**
+     * The scale factor derived from the overall motion between the current frame
+     * and the specified frame.
+     *
+     * The scale factor is always positive. A value of 1.0 indicates no
+     * scaling took place. Values between 0.0 and 1.0 indicate contraction
+     * and values greater than 1.0 indicate expansion.
+     *
+     * \include Frame_scaleFactor.txt
+     *
+     * The Leap Motion software derives scaling from the relative inward or outward motion of
+     * all objects detected in the field of view (independent of translation
+     * and rotation).
+     *
+     * If either this frame or sinceFrame is an invalid Frame object, then this
+     * method returns 1.0.
+     *
+     * @param sinceFrame The starting frame for computing the relative scaling.
+     * @returns A positive value representing the heuristically determined
+     * scaling change ratio between the current frame and that specified in the
+     * sinceFrame parameter.
+     * @since 1.0
+     */
+    LEAP_EXPORT float scaleFactor(const Frame& sinceFrame) const;
+
+    /**
+     * The estimated probability that the overall motion between the current
+     * frame and the specified frame is intended to be a scaling motion.
+     *
+     * \include Frame_scaleProbability.txt
+     *
+     * If either this frame or sinceFrame is an invalid Frame object, then this
+     * method returns zero.
+     *
+     * @param sinceFrame The starting frame for computing the relative scaling.
+     * @returns A value between 0 and 1 representing the estimated probability
+     * that the overall motion between the current frame and the specified frame
+     * is intended to be a scaling motion.
+     * @since 1.0
+     */
+    LEAP_EXPORT float scaleProbability(const Frame& sinceFrame) const;
+
+    /**
+     * The current InteractionBox for the frame. See the InteractionBox class
+     * documentation for more details on how this class should be used.
+     *
+     * \include Frame_interactionBox.txt
+     *
+     * @returns The current InteractionBox object.
+     * @since 1.0
+     */
+    LEAP_EXPORT InteractionBox interactionBox() const;
+
+    /**
+     * The instantaneous framerate.
+     *
+     * The rate at which the Leap Motion software is providing frames of data
+     * (in frames per second). The framerate can fluctuate depending on available computing
+     * resources, activity within the device field of view, software tracking settings,
+     * and other factors.
+     *
+     * \include Frame_currentFramesPerSecond.txt
+     *
+     * @returns An estimate of frames per second of the Leap Motion Controller.
+     * @since 1.0
+     */
+    LEAP_EXPORT float currentFramesPerSecond() const;
+
+    /**
+     * Reports whether this Frame instance is valid.
+     *
+     * A valid Frame is one generated by the Leap::Controller object that contains
+     * tracking data for all detected entities. An invalid Frame contains no
+     * actual tracking data, but you can call its functions without risk of a
+     * null pointer exception. The invalid Frame mechanism makes it more
+     * convenient to track individual data across the frame history. For example,
+     * you can invoke:
+     *
+     * \include Frame_Valid_Chain.txt
+     *
+     * for an arbitrary Frame history value, "n", without first checking whether
+     * frame(n) returned a null object. (You should still check that the
+     * returned Finger instance is valid.)
+     *
+     * @returns True, if this is a valid Frame object; false otherwise.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isValid() const;
+
+    /**
+     * Returns an invalid Frame object.
+     *
+     * You can use the instance returned by this function in comparisons testing
+     * whether a given Frame instance is valid or invalid. (You can also use the
+     * Frame::isValid() function.)
+     *
+     * \include Frame_Invalid_Demo.txt
+     *
+     * @returns The invalid Frame instance.
+     * @since 1.0
+     */
+    LEAP_EXPORT static const Frame& invalid();
+
+    /**
+     * Compare Frame object equality.
+     *
+     * \include Frame_operator_equals.txt
+     *
+     * Two Frame objects are equal if and only if both Frame objects represent
+     * the exact same frame of tracking data and both Frame objects are valid.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator==(const Frame&) const;
+
+    /**
+     * Compare Frame object inequality.
+     *
+     * \include Frame_operator_not_equals.txt
+     *
+     * Two Frame objects are equal if and only if both Frame objects represent
+     * the exact same frame of tracking data and both Frame objects are valid.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool operator!=(const Frame&) const;
+
+    /**
+     * Writes a brief, human readable description of the Frame object to an output stream.
+     *
+     * \include Frame_operator_stream.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT friend std::ostream& operator<<(std::ostream&, const Frame&);
+
+    /**
+     * A string containing a brief, human readable description of the Frame object.
+     *
+     * @returns A description of the Frame as a string.
+     * @since 1.0
+     */
+    LEAP_EXPORT std::string toString() const;
+  };
+
+  /**
+   * The Config class provides access to Leap Motion system configuration information.
+   *
+   * You can get and set gesture configuration parameters using the Config object
+   * obtained from a connected Controller object. The key strings required to
+   * identify a configuration parameter include:
+   *
+   * Key string | Value type | Default value | Units
+   * -----------|------------|---------------|------
+   * Gesture.Circle.MinRadius | float | 5.0 | mm
+   * Gesture.Circle.MinArc | float | 1.5*pi | radians
+   * Gesture.Swipe.MinLength | float | 150 | mm
+   * Gesture.Swipe.MinVelocity | float | 1000 | mm/s
+   * Gesture.KeyTap.MinDownVelocity | float | 50 | mm/s
+   * Gesture.KeyTap.HistorySeconds | float | 0.1 | s
+   * Gesture.KeyTap.MinDistance | float | 3.0 | mm
+   * Gesture.ScreenTap.MinForwardVelocity  | float | 50 | mm/s
+   * Gesture.ScreenTap.HistorySeconds | float | 0.1 | s
+   * Gesture.ScreenTap.MinDistance | float | 5.0 | mm
+   *
+   * After setting a configuration value, you must call the Config::save method
+   * to commit the changes. The configuration value changes are not persistent;
+   * your application needs to set the values everytime it runs.
+   *
+   * @see CircleGesture
+   * @see KeyTapGesture
+   * @see ScreenTapGesture
+   * @see SwipeGesture
+   * @since 1.0
+   */
+  class Config : public Interface {
+  public:
+    /**
+     * Constructs a Config object. 
+     * Do not create your own Config objects. Get a Config object using
+     * the Controller::config() function.
+     *
+     * \include Config_Constructor.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT Config();
+
+    /**
+     * Enumerates the possible data types for configuration values.
+     *
+     * The Config::type() function returns an item from the ValueType enumeration.
+     * @since 1.0
+     */
+    enum ValueType {
+      /**
+       * The data type is unknown.
+       * @since 1.0
+       */
+      TYPE_UNKNOWN = 0,
+      /**
+       * A boolean value.
+       * @since 1.0
+       */
+      TYPE_BOOLEAN = 1,
+      /**
+       * A 32-bit integer.
+       * @since 1.0
+       */
+      TYPE_INT32   = 2,
+      /**
+       * A floating-point number.
+       * @since 1.0
+       */
+      TYPE_FLOAT   = 6,
+      /**
+       * A string of characters.
+       * @since 1.0
+       */
+      TYPE_STRING  = 8
+    };
+
+    /**
+     * Reports the natural data type for the value related to the specified key.
+     *
+     * \include Config_type.txt
+     *
+     * @param key The key for the looking up the value in the configuration dictionary.
+     * @returns The native data type of the value, that is, the type that does not
+     * require a data conversion.
+     * @since 1.0
+     */
+    LEAP_EXPORT ValueType type(const std::string& key) const;
+
+    /**
+     * Gets the boolean representation for the specified key.
+     *
+     * \include Config_getBool.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT bool getBool(const std::string& key) const;
+
+    /** Sets the boolean representation for the specified key.
+     *
+     * \include Config_setBool.txt
+     *
+     * @returns true on success, false on failure.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool setBool(const std::string& key, bool value);
+
+    /**
+     * Gets the 32-bit integer representation for the specified key.
+     *
+     * \include Config_getInt32.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT int32_t getInt32(const std::string& key) const;
+
+    /** Sets the 32-bit integer representation for the specified key.
+     *
+     * \include Config_setInt32.txt
+     *
+     * @returns true on success, false on failure.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool setInt32(const std::string& key, int32_t value);
+
+    /**
+     * Gets the floating point representation for the specified key.
+     *
+     * \include Config_getFloat.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT float getFloat(const std::string& key) const;
+
+    /** Sets the floating point representation for the specified key.
+     *
+     * \include Config_setFloat.txt
+     *
+     * @returns true on success, false on failure.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool setFloat(const std::string& key, float value);
+
+    /**
+     * Gets the string representation for the specified key.
+     *
+     * \include Config_getString.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT std::string getString(const std::string& key) const;
+
+    /** Sets the string representation for the specified key.
+     *
+     * \include Config_setString.txt
+     *
+     * @returns true on success, false on failure.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool setString(const std::string& key, const std::string& value);
+
+    /**
+     * Saves the current state of the config.
+     *
+     * Call ``save()`` after making a set of configuration changes. The
+     * ``save()`` function transfers the configuration changes to the Leap Motion
+     * service. The configuration value changes are not persistent; your
+     * application must set the values everytime it runs.
+     *
+     * \include Config_save.txt
+     *
+     * @returns true on success, false on failure.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool save();
+  };
+
+  /**
+   * The Controller class is your main interface to the Leap Motion Controller.
+   *
+   * Create an instance of this Controller class to access frames of tracking
+   * data and configuration information. Frame data can be polled at any time
+   * using the Controller::frame() function. Call frame() or frame(0) to get the
+   * most recent frame. Set the history parameter to a positive integer to access
+   * previous frames. A controller stores up to 60 frames in its frame history.
+   *
+   * Polling is an appropriate strategy for applications which already have an
+   * intrinsic update loop, such as a game. You can also add an instance of a
+   * subclass of Leap::Listener to the controller to handle events as they occur.
+   * The Controller dispatches events to the listener upon initialization and exiting,
+   * on connection changes, when the application gains and loses the OS input focus,
+   * and when a new frame of tracking data is available.
+   * When these events occur, the controller object invokes the appropriate
+   * callback function defined in your subclass of Listener.
+   *
+   * To access frames of tracking data as they become available:
+   *
+   * 1. Implement a subclass of the Listener class and override the
+   *    Listener::onFrame() function.
+   * 2. In your Listener::onFrame() function, call the Controller::frame()
+   *    function to access the newest frame of tracking data.
+   * 3. To start receiving frames, create a Controller object and add an instance
+   *    of the Listener subclass to the Controller::addListener() function.
+   *
+   * When an instance of a Listener subclass is added to a Controller object,
+   * it calls the Listener::onInit() function when the listener is ready for use.
+   * When a connection is established between the controller and the Leap Motion software,
+   * the controller calls the Listener::onConnect() function. At this point, your
+   * application will start receiving frames of data. The controller calls the
+   * Listener::onFrame() function each time a new frame is available. If the
+   * controller loses its connection with the Leap Motion software or device for any
+   * reason, it calls the Listener::onDisconnect() function. If the listener is
+   * removed from the controller or the controller is destroyed, it calls the
+   * Listener::onExit() function. At that point, unless the listener is added to
+   * another controller again, it will no longer receive frames of tracking data.
+   *
+   * The Controller object is multithreaded and calls the Listener functions on
+   * its own thread, not on an application thread.
+   * @since 1.0
+   */
+  class Controller : public Interface {
+  public:
+    // For internal use only.
+    Controller(ControllerImplementation*);
+
+    /**
+     * Constructs a Controller object.
+     *
+     * When creating a Controller object, you may optionally pass in a
+     * reference to an instance of a subclass of Leap::Listener. Alternatively,
+     * you may add a listener using the Controller::addListener() function.
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT Controller();
+    LEAP_EXPORT virtual ~Controller();
+    /**
+     * Constructs a Controller object.
+     *
+     * When creating a Controller object, you may optionally pass in a
+     * reference to an instance of a subclass of Leap::Listener. Alternatively,
+     * you may add a listener using the Controller::addListener() function.
+     *
+     * \include Controller_Controller.txt
+     *
+     * @param listener An instance of Leap::Listener implementing the callback
+     * functions for the Leap Motion events you want to handle in your application.
+     * @since 1.0
+     */
+    LEAP_EXPORT Controller(Listener& listener);
+
+    /**
+     * Reports whether this Controller is connected to the Leap Motion service and 
+     * the Leap Motion hardware is plugged in.
+     *
+     * When you first create a Controller object, isConnected() returns false.
+     * After the controller finishes initializing and connects to the Leap Motion 
+     * software and if the Leap Motion hardware is plugged in, isConnected() returns true.
+     *
+     * You can either handle the onConnect event using a Listener instance or
+     * poll the isConnected() function if you need to wait for your
+     * application to be connected to the Leap Motion software before performing some other
+     * operation.
+     *
+     * \include Controller_isConnected.txt
+     * @returns True, if connected; false otherwise.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isConnected() const;
+
+    /**
+     * Reports whether this application is the focused, foreground application.
+     *
+     * By default, your application only receives tracking information from
+     * the Leap Motion controller when it has the operating system input focus.
+     * To receive tracking data when your application is in the background,
+     * the background frames policy flag must be set.
+     *
+     * \include Controller_hasFocus.txt
+     *
+     * @returns True, if application has focus; false otherwise.
+     *
+     * @see Controller::setPolicyFlags()
+     * @since 1.0
+     */
+    LEAP_EXPORT bool hasFocus() const;
+
+    /**
+     * The supported controller policies.
+     *
+     * Currently, the only supported policy is the background frames policy,
+     * which determines whether your application receives frames of tracking
+     * data when it is not the focused, foreground application.
+     * @since 1.0
+     */
+    enum PolicyFlag {
+      /**
+       * The default policy.
+       * @since 1.0
+       */
+      POLICY_DEFAULT = 0,
+      /**
+       * Receive background frames.
+       * @since 1.0
+       */
+      POLICY_BACKGROUND_FRAMES = (1 << 0)
+    };
+
+    /**
+     * Gets the active policy settings.
+     *
+     * Use this function to determine the current policy state.
+     * Keep in mind that setting a policy flag is asynchronous, so changes are
+     * not effective immediately after calling setPolicyFlag(). In addition, a
+     * policy request can be declined by the user. You should always set the
+     * policy flags required by your application at startup and check that the
+     * policy change request was successful after an appropriate interval.
+     *
+     * If the controller object is not connected to the Leap Motion software, then the default
+     * policy state is returned.
+     *
+     * \include Controller_policyFlags.txt
+     *
+     * @returns The current policy flags.
+     * @since 1.0
+     */
+    LEAP_EXPORT PolicyFlag policyFlags() const;
+
+    /**
+     * Requests a change in policy.
+     *
+     * A request to change a policy is subject to user approval and a policy
+     * can be changed by the user at any time (using the Leap Motion settings dialog).
+     * The desired policy flags must be set every time an application runs.
+     *
+     * Policy changes are completed asynchronously and, because they are subject
+     * to user approval, may not complete successfully. Call
+     * Controller::policyFlags() after a suitable interval to test whether
+     * the change was accepted.
+     *
+     * Currently, the background frames policy is the only policy supported.
+     * The background frames policy determines whether an application
+     * receives frames of tracking data while in the background. By
+     * default, the Leap Motion  software only sends tracking data to the foreground application.
+     * Only applications that need this ability should request the background
+     * frames policy.
+     *
+     * At this time, you can use the Leap Motion Settings dialog to
+     * globally enable or disable the background frames policy. However,
+     * each application that needs tracking data while in the background
+     * must also set the policy flag using this function.
+     *
+     * This function can be called before the Controller object is connected,
+     * but the request will be sent to the Leap Motion software after the Controller connects.
+     *
+     * \include Controller_setPolicyFlags.txt
+     *
+     * @param flags A PolicyFlag value indicating the policies to request.
+     * @since 1.0
+     */
+    LEAP_EXPORT void setPolicyFlags(PolicyFlag flags) const;
+
+    /**
+     * Adds a listener to this Controller.
+     *
+     * The Controller dispatches Leap Motion events to each associated listener. The
+     * order in which listener callback functions are invoked is arbitrary. If
+     * you pass a listener to the Controller's constructor function, it is
+     * automatically added to the list and can be removed with the
+     * Controller::removeListener() function.
+     *
+     * \include Controller_addListener.txt
+     *
+     * @param listener A subclass of Leap::Listener implementing the callback
+     * functions for the Leap Motion events you want to handle in your application.
+     * @returns Whether or not the listener was successfully added to the list
+     * of listeners.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool addListener(Listener& listener);
+
+    /**
+     * Remove a listener from the list of listeners that will receive Leap Motion
+     * events. A listener must be removed if its lifetime is shorter than the
+     * controller to which it is listening.
+     *
+     * \include Controller_removeListener.txt
+     *
+     * @param listener The listener to remove.
+     * @returns Whether or not the listener was successfully removed from the
+     * list of listeners.
+     * @since 1.0
+     */
+    LEAP_EXPORT bool removeListener(Listener& listener);
+
+    /**
+     * Returns a frame of tracking data from the Leap Motion software. Use the optional
+     * history parameter to specify which frame to retrieve. Call frame() or
+     * frame(0) to access the most recent frame; call frame(1) to access the
+     * previous frame, and so on. If you use a history value greater than the
+     * number of stored frames, then the controller returns an invalid frame.
+     *
+     * \include Controller_Frame_1.txt
+     *
+     * You can call this function in your Listener implementation to get frames at the
+     * Leap Motion frame rate:
+     *
+     * \include Controller_Listener_onFrame.txt
+     
+     * @param history The age of the frame to return, counting backwards from
+     * the most recent frame (0) into the past and up to the maximum age (59).
+     * @returns The specified frame; or, if no history parameter is specified,
+     * the newest frame. If a frame is not available at the specified history
+     * position, an invalid Frame is returned.
+     * @since 1.0
+     */
+    LEAP_EXPORT Frame frame(int history = 0) const;
+
+    /**
+     * Returns a Config object, which you can use to query the Leap Motion system for
+     * configuration information.
+     *
+     * \include Controller_config.txt
+     *
+     * @since 1.0
+     */
+    LEAP_EXPORT Config config() const;
+
+    /**
+     * The list of currently attached and recognized Leap Motion controller devices.
+     *
+     * The Device objects in the list describe information such as the range and
+     * tracking volume.
+     *
+     * \include Controller_devices.txt
+     *
+     * Currently, the Leap Motion Controller only recognizes a single device at a time.
+     * @since 1.0
+     */
+    LEAP_EXPORT DeviceList devices() const;
+
+    /*
+     * The Screen and ScreenList classes are currently unsupported.
+     *
+     * We are re-evaluating this feature due to the cumbersome location process
+     * required to use it and the amount of confusion about the feature's purpose.
+     *
+     * The list of screens whose positions have been identified by using the
+     * Leap Motion Screen Locator.
+     *
+     * The list always contains at least one entry representing the default
+     * screen. If the user has not registered the location of this default
+     * screen, then the coordinates, directions, and other values reported by
+     * the functions in its Screen object will not be accurate. Other monitor
+     * screens only appear in the list if their positions have been registered
+     * using the Leap Motion Screen Locator.
+     *
+     * A Screen object represents the position and orientation of a display
+     * monitor screen within the Leap Motion coordinate system.
+     * For example, if the screen location is known, you can get Leap Motion coordinates
+     * for the bottom-left corner of the screen. Registering the screen
+     * location also allows the Leap Motion software to calculate the point on the screen at
+     * which a finger or tool is pointing.
+     *
+     * A user can run the Screen Locator tool from the Leap Motion
+     * Settings dialog. Avoid assuming that a screen location is known or that
+     * an existing position is still correct. The registered position is only
+     * valid as long as the relative position of the Leap Motion Controller and the
+     * monitor screen remain constant.
+     *
+     * \include Screen_Closest_1.txt
+     *
+     * @returns ScreenList A list containing the screens whose positions have
+     * been registered by the user using the Screen Locator tool.
+     * The list always contains at least one entry representing the default
+     * monitor. If the user has not run the Screen Locator or has moved the Leap
+     * Motion device or screen since running it, the Screen object for this entry
+     * only contains default values.
+     * @since 1.0
+     */
+    LEAP_EXPORT ScreenList locatedScreens() const;
+
+    /**
+     * Enables or disables reporting of a specified gesture type.
+     *
+     * By default, all gesture types are disabled. When disabled, gestures of the
+     * disabled type are never reported and will not appear in the frame
+     * gesture list.
+     *
+     * \include Controller_enableGesture.txt
+     *
+     * As a performance optimization, only enable recognition for the types
+     * of movements that you use in your application.
+     *
+     * @param type The type of gesture to enable or disable. Must be a
+     * member of the Gesture::Type enumeration.
+     * @param enable True, to enable the specified gesture type; False,
+     * to disable.
+     * @see Controller::isGestureEnabled()
+     * @since 1.0
+     */
+    LEAP_EXPORT void enableGesture(Gesture::Type type, bool enable = true) const;
+
+    /**
+     * Reports whether the specified gesture type is enabled.
+     *
+     * \include Controller_isGestureEnabled.txt
+     *
+     * @return True, if the specified type is enabled; false, otherwise.
+     * @see Controller::enableGesture()
+     * @since 1.0
+     */
+    LEAP_EXPORT bool isGestureEnabled(Gesture::Type type) const;
+  };
+
+  /**
+   * The Listener class defines a set of callback functions that you can
+   * override in a subclass to respond to events dispatched by the Controller object.
+   *
+   * To handle Leap Motion events, create an instance of a Listener subclass and assign
+   * it to the Controller instance. The Controller calls the relevant Listener
+   * callback function when an event occurs, passing in a reference to itself.
+   * You do not have to implement callbacks for events you do not want to handle.
+   *
+   * The Controller object calls these Listener functions from a thread created
+   * by the Leap Motion library, not the thread used to create or set the Listener instance.
+   * @since 1.0
+   */
+  class Listener {
+  public:
+    /**
+     * Constructs a Listener object.
+     * @since 1.0
+     */
+    LEAP_EXPORT Listener() {}
+
+    /**
+     * Destroys this Listener object.
+     */
+    LEAP_EXPORT virtual ~Listener() {}
+
+    /**
+     * Called once, when this Listener object is newly added to a Controller.
+     *
+     * \include Listener_onInit.txt
+     *
+     * @param controller The Controller object invoking this callback function.
+     * @since 1.0
+     */
+    LEAP_EXPORT virtual void onInit(const Controller&) {}
+
+    /**
+     * Called when the Controller object connects to the Leap Motion software and 
+     * the Leap Motion hardware device is plugged in,
+     * or when this Listener object is added to a Controller that is already connected.
+     *
+     * \include Listener_onConnect.txt
+     *
+     * @param controller The Controller object invoking this callback function.
+     * @since 1.0
+     */
+    LEAP_EXPORT virtual void onConnect(const Controller&) {}
+
+    /**
+     * Called when the Controller object disconnects from the Leap Motion software or
+     * the Leap Motion hardware is unplugged.
+     * The controller can disconnect when the Leap Motion device is unplugged, the
+     * user shuts the Leap Motion software down, or the Leap Motion software encounters an
+     * unrecoverable error.
+     *
+     * \include Listener_onDisconnect.txt
+     *
+     * Note: When you launch a Leap-enabled application in a debugger, the
+     * Leap Motion library does not disconnect from the application. This is to allow
+     * you to step through code without losing the connection because of time outs.
+     *
+     * @param controller The Controller object invoking this callback function.
+     * @since 1.0
+     */
+    LEAP_EXPORT virtual void onDisconnect(const Controller&) {}
+
+    /**
+     * Called when this Listener object is removed from the Controller
+     * or the Controller instance is destroyed.
+     *
+     * \include Listener_onExit.txt
+     *
+     * @param controller The Controller object invoking this callback function.
+     * @since 1.0
+     */
+    LEAP_EXPORT virtual void onExit(const Controller&) {}
+
+    /**
+     * Called when a new frame of hand and finger tracking data is available.
+     * Access the new frame data using the Controller::frame() function.
+     *
+     * \include Listener_onFrame.txt
+     *
+     * Note, the Controller skips any pending onFrame events while your
+     * onFrame handler executes. If your implementation takes too long to return,
+     * one or more frames can be skipped. The Controller still inserts the skipped
+     * frames into the frame history. You can access recent frames by setting
+     * the history parameter when calling the Controller::frame() function.
+     * You can determine if any pending onFrame events were skipped by comparing
+     * the ID of the most recent frame with the ID of the last received frame.
+     *
+     * @param controller The Controller object invoking this callback function.
+     * @since 1.0
+     */
+    LEAP_EXPORT virtual void onFrame(const Controller&) {}
+
+    /**
+     * Called when this application becomes the foreground application.
+     *
+     * Only the foreground application receives tracking data from the Leap
+     * Motion Controller. This function is only called when the controller
+     * object is in a connected state.
+     *
+     * \include Listener_onFocusGained.txt
+     *
+     * @param controller The Controller object invoking this callback function.
+     * @since 1.0
+     */
+    LEAP_EXPORT virtual void onFocusGained(const Controller&) {}
+
+    /**
+     * Called when this application loses the foreground focus.
+     *
+     * Only the foreground application receives tracking data from the Leap
+     * Motion Controller. This function is only called when the controller
+     * object is in a connected state.
+     *
+     * \include Listener_onFocusLost.txt
+     *
+     * @param controller The Controller object invoking this callback function.
+     * @since 1.0
+     */
+    LEAP_EXPORT virtual void onFocusLost(const Controller&) {}
+  };
+
+}
+
+#endif // __Leap_h__

+ 1036 - 0
engine/lib/LeapSDK/include/LeapMath.h

@@ -0,0 +1,1036 @@
+/******************************************************************************\
+* Copyright (C) 2012-2013 Leap Motion, Inc. All rights reserved.               *
+* Leap Motion proprietary and confidential. Not for distribution.              *
+* Use subject to the terms of the Leap Motion SDK Agreement available at       *
+* https://developer.leapmotion.com/sdk_agreement, or another agreement         *
+* between Leap Motion and you, your company or other organization.             *
+\******************************************************************************/
+
+#if !defined(__LeapMath_h__)
+#define __LeapMath_h__
+
+#include <cmath>
+#include <iostream>
+#include <sstream>
+#include <float.h>
+
+namespace Leap {
+
+/**
+ * The constant pi as a single precision floating point number.
+ * @since 1.0
+ */
+static const float PI          = 3.1415926536f;
+/**
+ * The constant ratio to convert an angle measure from degrees to radians.
+ * Multiply a value in degrees by this constant to convert to radians.
+ * @since 1.0
+ */
+static const float DEG_TO_RAD  = 0.0174532925f;
+/**
+ * The constant ratio to convert an angle measure from radians to degrees.
+ * Multiply a value in radians by this constant to convert to degrees.
+ * @since 1.0
+ */
+static const float RAD_TO_DEG  = 57.295779513f;
+
+/**
+ * The Vector struct represents a three-component mathematical vector or point
+ * such as a direction or position in three-dimensional space.
+ *
+ * The Leap Motion software employs a right-handed Cartesian coordinate system.
+ * Values given are in units of real-world millimeters. The origin is centered
+ * at the center of the Leap Motion Controller. The x- and z-axes lie in the horizontal
+ * plane, with the x-axis running parallel to the long edge of the device.
+ * The y-axis is vertical, with positive values increasing upwards (in contrast
+ * to the downward orientation of most computer graphics coordinate systems).
+ * The z-axis has positive values increasing away from the computer screen.
+ *
+ * \image html images/Leap_Axes.png
+ * @since 1.0
+ */
+struct Vector {
+  /**
+   * Creates a new Vector with all components set to zero.
+   * @since 1.0
+   */
+  Vector() :
+    x(0), y(0), z(0) {}
+
+  /**
+   * Creates a new Vector with the specified component values.
+   *
+   * \include Vector_Constructor_1.txt
+   * @since 1.0
+   */
+  Vector(float _x, float _y, float _z) :
+    x(_x), y(_y), z(_z) {}
+
+  /**
+   * Copies the specified Vector.
+   *
+   * \include Vector_Constructor_2.txt
+   * @since 1.0
+   */
+  Vector(const Vector& vector) :
+    x(vector.x), y(vector.y), z(vector.z) {}
+
+  /**
+   * The zero vector: (0, 0, 0)
+   *
+   * \include Vector_Zero.txt
+   * @since 1.0
+   */
+  static const Vector& zero() {
+    static Vector s_zero(0, 0, 0);
+    return s_zero;
+  }
+
+  /**
+   * The x-axis unit vector: (1, 0, 0)
+   *
+   * \include Vector_XAxis.txt
+   * @since 1.0
+   */
+  static const Vector& xAxis() {
+    static Vector s_xAxis(1, 0, 0);
+    return s_xAxis;
+  }
+  /**
+   * The y-axis unit vector: (0, 1, 0)
+   *
+   * \include Vector_YAxis.txt
+   * @since 1.0
+   */
+  static const Vector& yAxis() {
+    static Vector s_yAxis(0, 1, 0);
+    return s_yAxis;
+  }
+  /**
+   * The z-axis unit vector: (0, 0, 1)
+   *
+   * \include Vector_ZAxis.txt
+   * @since 1.0
+   */
+  static const Vector& zAxis() {
+    static Vector s_zAxis(0, 0, 1);
+    return s_zAxis;
+  }
+
+  /**
+   * The unit vector pointing left along the negative x-axis: (-1, 0, 0)
+   *
+   * \include Vector_Left.txt
+   * @since 1.0
+   */
+  static const Vector& left() {
+    static Vector s_left(-1, 0, 0);
+    return s_left;
+  }
+  /**
+   * The unit vector pointing right along the positive x-axis: (1, 0, 0)
+   *
+   * \include Vector_Right.txt
+   * @since 1.0
+   */
+  static const Vector& right() {
+    return xAxis();
+  }
+  /**
+   * The unit vector pointing down along the negative y-axis: (0, -1, 0)
+   *
+   * \include Vector_Down.txt
+   * @since 1.0
+   */
+  static const Vector& down() {
+    static Vector s_down(0, -1, 0);
+    return s_down;
+  }
+  /**
+   * The unit vector pointing up along the positive y-axis: (0, 1, 0)
+   *
+   * \include Vector_Up.txt
+   * @since 1.0
+   */
+  static const Vector& up() {
+    return yAxis();
+  }
+  /**
+   * The unit vector pointing forward along the negative z-axis: (0, 0, -1)
+   *
+   * \include Vector_Forward.txt
+   * @since 1.0
+   */
+  static const Vector& forward() {
+    static Vector s_forward(0, 0, -1);
+    return s_forward;
+  }
+  /**
+   * The unit vector pointing backward along the positive z-axis: (0, 0, 1)
+   *
+   * \include Vector_Backward.txt
+   * @since 1.0
+   */
+  static const Vector& backward() {
+    return zAxis();
+  }
+
+  /**
+   * The magnitude, or length, of this vector.
+   *
+   * The magnitude is the L2 norm, or Euclidean distance between the origin and
+   * the point represented by the (x, y, z) components of this Vector object.
+   *
+   * \include Vector_Magnitude.txt
+   *
+   * @returns The length of this vector.
+   * @since 1.0
+   */
+  float magnitude() const {
+    return std::sqrt(x*x + y*y + z*z);
+  }
+
+  /**
+   * The square of the magnitude, or length, of this vector.
+   *
+   * \include Vector_Magnitude_Squared.txt
+   *
+   * @returns The square of the length of this vector.
+   * @since 1.0
+   */
+  float magnitudeSquared() const {
+    return x*x + y*y + z*z;
+  }
+
+  /**
+   * The distance between the point represented by this Vector
+   * object and a point represented by the specified Vector object.
+   *
+   * \include Vector_DistanceTo.txt
+   *
+   * @param other A Vector object.
+   * @returns The distance from this point to the specified point.
+   * @since 1.0
+   */
+  float distanceTo(const Vector& other) const {
+    return std::sqrt((x - other.x)*(x - other.x) +
+                     (y - other.y)*(y - other.y) +
+                     (z - other.z)*(z - other.z));
+  }
+
+  /**
+   * The angle between this vector and the specified vector in radians.
+   *
+   * The angle is measured in the plane formed by the two vectors. The
+   * angle returned is always the smaller of the two conjugate angles.
+   * Thus <tt>A.angleTo(B) == B.angleTo(A)</tt> and is always a positive
+   * value less than or equal to pi radians (180 degrees).
+   *
+   * If either vector has zero length, then this function returns zero.
+   *
+   * \image html images/Math_AngleTo.png
+   *
+   * \include Vector_AngleTo.txt
+   *
+   * @param other A Vector object.
+   * @returns The angle between this vector and the specified vector in radians.
+   * @since 1.0
+   */
+  float angleTo(const Vector& other) const {
+    float denom = this->magnitudeSquared() * other.magnitudeSquared();
+    if (denom <= 0.0f) {
+      return 0.0f;
+    }
+    return std::acos(this->dot(other) / std::sqrt(denom));
+  }
+
+  /**
+   * The pitch angle in radians.
+   *
+   * Pitch is the angle between the negative z-axis and the projection of
+   * the vector onto the y-z plane. In other words, pitch represents rotation
+   * around the x-axis.
+   * If the vector points upward, the returned angle is between 0 and pi radians
+   * (180 degrees); if it points downward, the angle is between 0 and -pi radians.
+   *
+   * \image html images/Math_Pitch_Angle.png
+   *
+   * \include Vector_Pitch.txt
+   *
+   * @returns The angle of this vector above or below the horizon (x-z plane).
+   * @since 1.0
+   */
+  float pitch() const {
+    return std::atan2(y, -z);
+  }
+
+  /**
+   * The yaw angle in radians.
+   *
+   * Yaw is the angle between the negative z-axis and the projection of
+   * the vector onto the x-z plane. In other words, yaw represents rotation
+   * around the y-axis. If the vector points to the right of the negative z-axis,
+   * then the returned angle is between 0 and pi radians (180 degrees);
+   * if it points to the left, the angle is between 0 and -pi radians.
+   *
+   * \image html images/Math_Yaw_Angle.png
+   *
+   * \include Vector_Yaw.txt
+   *
+   * @returns The angle of this vector to the right or left of the negative z-axis.
+   * @since 1.0
+   */
+  float yaw() const {
+    return std::atan2(x, -z);
+  }
+
+  /**
+   * The roll angle in radians.
+   *
+   * Roll is the angle between the y-axis and the projection of
+   * the vector onto the x-y plane. In other words, roll represents rotation
+   * around the z-axis. If the vector points to the left of the y-axis,
+   * then the returned angle is between 0 and pi radians (180 degrees);
+   * if it points to the right, the angle is between 0 and -pi radians.
+   *
+   * \image html images/Math_Roll_Angle.png
+   *
+   * Use this function to get roll angle of the plane to which this vector is a
+   * normal. For example, if this vector represents the normal to the palm,
+   * then this function returns the tilt or roll of the palm plane compared
+   * to the horizontal (x-z) plane.
+   *
+   * \include Vector_Roll.txt
+   *
+   * @returns The angle of this vector to the right or left of the y-axis.
+   * @since 1.0
+   */
+  float roll() const {
+    return std::atan2(x, -y);
+  }
+
+  /**
+   * The dot product of this vector with another vector.
+   *
+   * The dot product is the magnitude of the projection of this vector
+   * onto the specified vector.
+   *
+   * \image html images/Math_Dot.png
+   *
+   * \include Vector_Dot.txt
+   *
+   * @param other A Vector object.
+   * @returns The dot product of this vector and the specified vector.
+   * @since 1.0
+   */
+  float dot(const Vector& other) const {
+    return (x * other.x) + (y * other.y) + (z * other.z);
+  }
+
+  /**
+   * The cross product of this vector and the specified vector.
+   *
+   * The cross product is a vector orthogonal to both original vectors.
+   * It has a magnitude equal to the area of a parallelogram having the
+   * two vectors as sides. The direction of the returned vector is
+   * determined by the right-hand rule. Thus <tt>A.cross(B) == -B.cross(A).</tt>
+   *
+   * \image html images/Math_Cross.png
+   *
+   * \include Vector_Cross.txt
+   *
+   * @param other A Vector object.
+   * @returns The cross product of this vector and the specified vector.
+   * @since 1.0
+   */
+  Vector cross(const Vector& other) const {
+    return Vector((y * other.z) - (z * other.y),
+                  (z * other.x) - (x * other.z),
+                  (x * other.y) - (y * other.x));
+  }
+
+  /**
+   * A normalized copy of this vector.
+   *
+   * A normalized vector has the same direction as the original vector,
+   * but with a length of one.
+   *
+   * \include Vector_Normalized.txt
+   *
+   * @returns A Vector object with a length of one, pointing in the same
+   * direction as this Vector object.
+   * @since 1.0
+   */
+  Vector normalized() const {
+    float denom = this->magnitudeSquared();
+    if (denom <= 0.0f) {
+      return Vector::zero();
+    }
+    denom = 1.0f / std::sqrt(denom);
+    return Vector(x * denom, y * denom, z * denom);
+  }
+
+  /**
+   * A copy of this vector pointing in the opposite direction.
+   *
+   * \include Vector_Negate.txt
+   *
+   * @returns A Vector object with all components negated.
+   * @since 1.0
+   */
+  Vector operator-() const {
+    return Vector(-x, -y, -z);
+  }
+
+  /**
+   * Add vectors component-wise.
+   *
+   * \include Vector_Plus.txt
+   * @since 1.0
+   */
+  Vector operator+(const Vector& other) const {
+    return Vector(x + other.x, y + other.y, z + other.z);
+  }
+
+  /**
+   * Subtract vectors component-wise.
+   *
+   * \include Vector_Minus.txt
+   * @since 1.0
+   */
+  Vector operator-(const Vector& other) const {
+    return Vector(x - other.x, y - other.y, z - other.z);
+  }
+
+  /**
+   * Multiply vector by a scalar.
+   *
+   * \include Vector_Times.txt
+   * @since 1.0
+   */
+  Vector operator*(float scalar) const {
+    return Vector(x * scalar, y * scalar, z * scalar);
+  }
+
+  /**
+   * Divide vector by a scalar.
+   *
+   * \include Vector_Divide.txt
+   * @since 1.0
+   */
+  Vector operator/(float scalar) const {
+    return Vector(x / scalar, y / scalar, z / scalar);
+  }
+
+#if !defined(SWIG)
+  /**
+   * Multiply vector by a scalar on the left-hand side (C++ only).
+   *
+   * \include Vector_Left_Times.txt
+   * @since 1.0
+   */
+  friend Vector operator*(float scalar, const Vector& vector) {
+    return Vector(vector.x * scalar, vector.y * scalar, vector.z * scalar);
+  }
+#endif
+
+  /**
+   * Add vectors component-wise and assign the sum.
+   * @since 1.0
+   */
+  Vector& operator+=(const Vector& other) {
+    x += other.x;
+    y += other.y;
+    z += other.z;
+    return *this;
+  }
+
+  /**
+   * Subtract vectors component-wise and assign the difference.
+   * @since 1.0
+   */
+  Vector& operator-=(const Vector& other) {
+    x -= other.x;
+    y -= other.y;
+    z -= other.z;
+    return *this;
+  }
+
+  /**
+   * Multiply vector by a scalar and assign the product.
+   * @since 1.0
+   */
+  Vector& operator*=(float scalar) {
+    x *= scalar;
+    y *= scalar;
+    z *= scalar;
+    return *this;
+  }
+
+  /**
+   * Divide vector by a scalar and assign the quotient.
+   * @since 1.0
+   */
+  Vector& operator/=(float scalar) {
+    x /= scalar;
+    y /= scalar;
+    z /= scalar;
+    return *this;
+  }
+
+  /**
+   * Returns a string containing this vector in a human readable format: (x, y, z).
+   * @since 1.0
+   */
+  std::string toString() const {
+    std::stringstream result;
+    result << "(" << x << ", " << y << ", " << z << ")";
+    return result.str();
+  }
+  /**
+   * Writes the vector to the output stream using a human readable format: (x, y, z).
+   * @since 1.0
+   */
+  friend std::ostream& operator<<(std::ostream& out, const Vector& vector) {
+    return out << vector.toString();
+  }
+
+  /**
+   * Compare Vector equality component-wise.
+   *
+   * \include Vector_Equals.txt
+   * @since 1.0
+   */
+  bool operator==(const Vector& other) const {
+    return x == other.x && y == other.y && z == other.z;
+  }
+  /**
+   * Compare Vector inequality component-wise.
+   *
+   * \include Vector_NotEqual.txt
+   * @since 1.0
+   */
+  bool operator!=(const Vector& other) const {
+    return x != other.x || y != other.y || z != other.z;
+  }
+
+  /**
+   * Returns true if all of the vector's components are finite.  If any
+   * component is NaN or infinite, then this returns false.
+   *
+   * \include Vector_IsValid.txt
+   * @since 1.0
+   */
+  bool isValid() const {
+    return (x <= FLT_MAX && x >= -FLT_MAX) &&
+           (y <= FLT_MAX && y >= -FLT_MAX) &&
+           (z <= FLT_MAX && z >= -FLT_MAX);
+  }
+
+  /**
+   * Index vector components numerically.
+   * Index 0 is x, index 1 is y, and index 2 is z.
+   * @returns The x, y, or z component of this Vector, if the specified index
+   * value is at least 0 and at most 2; otherwise, returns zero.
+   *
+   * \include Vector_Index.txt
+   * @since 1.0
+   */
+  float operator[](unsigned int index) const {
+    return index < 3 ? (&x)[index] : 0.0f;
+  }
+
+  /**
+   * Cast the vector to a float array.
+   *
+   * \include Vector_ToFloatPointer.txt
+   * @since 1.0
+   */
+  const float* toFloatPointer() const {
+    return &x; /* Note: Assumes x, y, z are aligned in memory. */
+  }
+
+  /**
+   * Convert a Leap::Vector to another 3-component Vector type.
+   *
+   * The specified type must define a constructor that takes the x, y, and z
+   * components as separate parameters.
+   * @since 1.0
+   */
+  template<typename Vector3Type>
+  const Vector3Type toVector3() const {
+    return Vector3Type(x, y, z);
+  }
+
+  /**
+   * Convert a Leap::Vector to another 4-component Vector type.
+   *
+   * The specified type must define a constructor that takes the x, y, z, and w
+   * components as separate parameters. (The homogeneous coordinate, w, is set
+   * to zero by default, but you should typically set it to one for vectors
+   * representing a position.)
+   * @since 1.0
+   */
+  template<typename Vector4Type>
+  const Vector4Type toVector4(float w=0.0f) const {
+    return Vector4Type(x, y, z, w);
+  }
+
+  /**
+   * The horizontal component.
+   * @since 1.0
+   */
+  float x;
+  /**
+   * The vertical component.
+   * @since 1.0
+   */
+  float y;
+  /**
+   * The depth component.
+   * @since 1.0
+   */
+  float z;
+};
+
+
+/**
+ * The FloatArray struct is used to allow the returning of native float arrays
+ * without requiring dynamic memory allocation.  It represents a matrix
+ * with a size up to 4x4.
+ * @since 1.0
+ */
+struct FloatArray {
+  /**
+   * Access the elements of the float array exactly like a native array.
+   * @since 1.0
+   */
+  float& operator[] (unsigned int index) {
+    return m_array[index];
+  }
+
+  /**
+   * Use the Float Array anywhere a float pointer can be used.
+   * @since 1.0
+   */
+  operator float* () {
+    return m_array;
+  }
+
+  /**
+   * Use the Float Array anywhere a const float pointer can be used.
+   * @since 1.0
+   */
+  operator const float* () const {
+    return m_array;
+  }
+
+  /**
+   * An array containing up to 16 entries of the matrix.
+   * @since 1.0
+   */
+  float m_array[16];
+};
+
+/**
+ * The Matrix struct represents a transformation matrix.
+ *
+ * To use this struct to transform a Vector, construct a matrix containing the
+ * desired transformation and then use the Matrix::transformPoint() or
+ * Matrix::transformDirection() functions to apply the transform.
+ *
+ * Transforms can be combined by multiplying two or more transform matrices using
+ * the * operator.
+ * @since 1.0
+ */
+struct Matrix
+{
+  /**
+   * Constructs an identity transformation matrix.
+   *
+   * \include Matrix_Matrix.txt
+   *
+   * @since 1.0
+   */
+  Matrix() :
+    xBasis(1, 0, 0),
+    yBasis(0, 1, 0),
+    zBasis(0, 0, 1),
+    origin(0, 0, 0) {
+  }
+
+  /**
+   * Constructs a copy of the specified Matrix object.
+   *
+   * \include Matrix_Matrix_copy.txt
+   *
+   * @since 1.0
+   */
+  Matrix(const Matrix& other) :
+    xBasis(other.xBasis),
+    yBasis(other.yBasis),
+    zBasis(other.zBasis),
+    origin(other.origin) {
+  }
+
+  /**
+   * Constructs a transformation matrix from the specified basis vectors.
+   *
+   * \include Matrix_Matrix_basis.txt
+   *
+   * @param _xBasis A Vector specifying rotation and scale factors for the x-axis.
+   * @param _yBasis A Vector specifying rotation and scale factors for the y-axis.
+   * @param _zBasis A Vector specifying rotation and scale factors for the z-axis.
+   * @since 1.0
+   */
+  Matrix(const Vector& _xBasis, const Vector& _yBasis, const Vector& _zBasis) :
+    xBasis(_xBasis),
+    yBasis(_yBasis),
+    zBasis(_zBasis),
+    origin(0, 0, 0) {
+  }
+
+  /**
+   * Constructs a transformation matrix from the specified basis and translation vectors.
+   *
+   * \include Matrix_Matrix_basis_origin.txt
+   *
+   * @param _xBasis A Vector specifying rotation and scale factors for the x-axis.
+   * @param _yBasis A Vector specifying rotation and scale factors for the y-axis.
+   * @param _zBasis A Vector specifying rotation and scale factors for the z-axis.
+   * @param _origin A Vector specifying translation factors on all three axes.
+   * @since 1.0
+   */
+  Matrix(const Vector& _xBasis, const Vector& _yBasis, const Vector& _zBasis, const Vector& _origin) :
+    xBasis(_xBasis),
+    yBasis(_yBasis),
+    zBasis(_zBasis),
+    origin(_origin) {
+  }
+
+  /**
+   * Constructs a transformation matrix specifying a rotation around the specified vector.
+   *
+   * \include Matrix_Matrix_rotation.txt
+   *
+   * @param axis A Vector specifying the axis of rotation.
+   * @param angleRadians The amount of rotation in radians.
+   * @since 1.0
+   */
+  Matrix(const Vector& axis, float angleRadians) :
+    origin(0, 0, 0) {
+    setRotation(axis, angleRadians);
+  }
+
+  /**
+   * Constructs a transformation matrix specifying a rotation around the specified vector
+   * and a translation by the specified vector.
+   *
+   * \include Matrix_Matrix_rotation_translation.txt
+   *
+   * @param axis A Vector specifying the axis of rotation.
+   * @param angleRadians The angle of rotation in radians.
+   * @param translation A Vector representing the translation part of the transform.
+   * @since 1.0
+   */
+  Matrix(const Vector& axis, float angleRadians, const Vector& translation)
+    : origin(translation) {
+    setRotation(axis, angleRadians);
+  }
+
+  /**
+   * Returns the identity matrix specifying no translation, rotation, and scale.
+   *
+   * \include Matrix_identity.txt
+   *
+   * @returns The identity matrix.
+   * @since 1.0
+   */
+  static const Matrix& identity() {
+    static Matrix s_identity;
+    return s_identity;
+  }
+
+  /**
+   * Sets this transformation matrix to represent a rotation around the specified vector.
+   *
+   * \include Matrix_setRotation.txt
+   *
+   * This function erases any previous rotation and scale transforms applied
+   * to this matrix, but does not affect translation.
+   *
+   * @param axis A Vector specifying the axis of rotation.
+   * @param angleRadians The amount of rotation in radians.
+   * @since 1.0
+   */
+  void setRotation(const Vector& axis, float angleRadians) {
+    const Vector n = axis.normalized();
+    const float s = std::sin(angleRadians);
+    const float c = std::cos(angleRadians);
+    const float C = (1-c);
+
+    xBasis = Vector(n[0]*n[0]*C + c,      n[0]*n[1]*C - n[2]*s, n[0]*n[2]*C + n[1]*s);
+    yBasis = Vector(n[1]*n[0]*C + n[2]*s, n[1]*n[1]*C + c,      n[1]*n[2]*C - n[0]*s);
+    zBasis = Vector(n[2]*n[0]*C - n[1]*s, n[2]*n[1]*C + n[0]*s, n[2]*n[2]*C + c     );
+  }
+
+  /**
+   * Transforms a vector with this matrix by transforming its rotation,
+   * scale, and translation.
+   *
+   * \include Matrix_transformPoint.txt
+   *
+   * Translation is applied after rotation and scale.
+   *
+   * @param in The Vector to transform.
+   * @returns A new Vector representing the transformed original.
+   * @since 1.0
+   */
+  Vector transformPoint(const Vector& in) const {
+    return xBasis*in.x + yBasis*in.y + zBasis*in.z + origin;
+  }
+
+  /**
+   * Transforms a vector with this matrix by transforming its rotation and
+   * scale only.
+   *
+   * \include Matrix_transformDirection.txt
+   *
+   * @param in The Vector to transform.
+   * @returns A new Vector representing the transformed original.
+   * @since 1.0
+   */
+  Vector transformDirection(const Vector& in) const {
+    return xBasis*in.x + yBasis*in.y + zBasis*in.z;
+  }
+
+  /**
+   * Performs a matrix inverse if the matrix consists entirely of rigid
+   * transformations (translations and rotations).  If the matrix is not rigid,
+   * this operation will not represent an inverse.
+   *
+   * \include Matrix_rigidInverse.txt
+   *
+   * Note that all matricies that are directly returned by the API are rigid.
+   *
+   * @returns The rigid inverse of the matrix.
+   * @since 1.0
+   */
+  Matrix rigidInverse() const {
+    Matrix rotInverse = Matrix(Vector(xBasis[0], yBasis[0], zBasis[0]),
+                               Vector(xBasis[1], yBasis[1], zBasis[1]),
+                               Vector(xBasis[2], yBasis[2], zBasis[2]));
+    rotInverse.origin = rotInverse.transformDirection( -origin );
+    return rotInverse;
+  }
+
+  /**
+   * Multiply transform matrices.
+   *
+   * Combines two transformations into a single equivalent transformation.
+   *
+   * \include Matrix_operator_times.txt
+   *
+   * @param other A Matrix to multiply on the right hand side.
+   * @returns A new Matrix representing the transformation equivalent to
+   * applying the other transformation followed by this transformation.
+   * @since 1.0
+   */
+  Matrix operator*(const Matrix& other) const {
+    return Matrix(transformDirection(other.xBasis),
+                  transformDirection(other.yBasis),
+                  transformDirection(other.zBasis),
+                  transformPoint(other.origin));
+  }
+
+  /**
+   * Multiply transform matrices and assign the product.
+   *
+   * \include Matrix_operator_times_equal.txt
+   *
+   * @since 1.0
+   */
+  Matrix& operator*=(const Matrix& other) {
+    return (*this) = (*this) * other;
+  }
+
+  /**
+   * Compare Matrix equality component-wise.
+   *
+   * \include Matrix_operator_equals.txt
+   *
+   * @since 1.0
+   */
+  bool operator==(const Matrix& other) const {
+    return xBasis == other.xBasis &&
+           yBasis == other.yBasis &&
+           zBasis == other.zBasis &&
+           origin == other.origin;
+  }
+  /**
+   * Compare Matrix inequality component-wise.
+   *
+   * \include Matrix_operator_not_equals.txt
+   *
+   * @since 1.0
+   */
+  bool operator!=(const Matrix& other) const {
+    return xBasis != other.xBasis ||
+           yBasis != other.yBasis ||
+           zBasis != other.zBasis ||
+           origin != other.origin;
+  }
+
+  /**
+   * Convert a Leap::Matrix object to another 3x3 matrix type.
+   *
+   * The new type must define a constructor function that takes each matrix
+   * element as a parameter in row-major order.
+   *
+   * Translation factors are discarded.
+   * @since 1.0
+   */
+  template<typename Matrix3x3Type>
+  const Matrix3x3Type toMatrix3x3() const {
+    return Matrix3x3Type(xBasis.x, xBasis.y, xBasis.z,
+                         yBasis.x, yBasis.y, yBasis.z,
+                         zBasis.x, zBasis.y, zBasis.z);
+  }
+
+  /**
+   * Convert a Leap::Matrix object to another 4x4 matrix type.
+   *
+   * The new type must define a constructor function that takes each matrix
+   * element as a parameter in row-major order.
+   * @since 1.0
+   */
+  template<typename Matrix4x4Type>
+  const Matrix4x4Type toMatrix4x4() const {
+    return Matrix4x4Type(xBasis.x, xBasis.y, xBasis.z, 0.0f,
+                         yBasis.x, yBasis.y, yBasis.z, 0.0f,
+                         zBasis.x, zBasis.y, zBasis.z, 0.0f,
+                         origin.x, origin.y, origin.z, 1.0f);
+  }
+
+  /**
+   * Writes the 3x3 Matrix object to a 9 element row-major float or
+   * double array.
+   *
+   * Translation factors are discarded.
+   *
+   * Returns a pointer to the same data.
+   * @since 1.0
+   */
+  template<typename T>
+  T* toArray3x3(T* output) const {
+    output[0] = xBasis.x; output[1] = xBasis.y; output[2] = xBasis.z;
+    output[3] = yBasis.x; output[4] = yBasis.y; output[5] = yBasis.z;
+    output[6] = zBasis.x; output[7] = zBasis.y; output[8] = zBasis.z;
+    return output;
+  }
+
+  /**
+   * Convert a 3x3 Matrix object to a 9 element row-major float array.
+   *
+   * Translation factors are discarded.
+   *
+   * \include Matrix_toArray3x3.txt
+   *
+   * Returns a FloatArray struct to avoid dynamic memory allocation.
+   * @since 1.0
+   */
+  FloatArray toArray3x3() const {
+    FloatArray output;
+    toArray3x3((float*)output);
+    return output;
+  }
+
+  /**
+   * Writes the 4x4 Matrix object to a 16 element row-major float
+   * or double array.
+   *
+   * Returns a pointer to the same data.
+   * @since 1.0
+   */
+  template<typename T>
+  T* toArray4x4(T* output) const {
+    output[0]  = xBasis.x; output[1]  = xBasis.y; output[2]  = xBasis.z; output[3]  = 0.0f;
+    output[4]  = yBasis.x; output[5]  = yBasis.y; output[6]  = yBasis.z; output[7]  = 0.0f;
+    output[8]  = zBasis.x; output[9]  = zBasis.y; output[10] = zBasis.z; output[11] = 0.0f;
+    output[12] = origin.x; output[13] = origin.y; output[14] = origin.z; output[15] = 1.0f;
+    return output;
+  }
+
+  /**
+   * Convert a 4x4 Matrix object to a 16 element row-major float array.
+   *
+   * \include Matrix_toArray4x4.txt
+   *
+   * Returns a FloatArray struct to avoid dynamic memory allocation.
+   * @since 1.0
+   */
+  FloatArray toArray4x4() const {
+    FloatArray output;
+    toArray4x4((float*)output);
+    return output;
+  }
+
+  /**
+   * Write the matrix to a string in a human readable format.
+   * @since 1.0
+   */
+  std::string toString() const {
+    std::stringstream result;
+    result << "xBasis:" << xBasis.toString() << " yBasis:" << yBasis.toString()
+           << " zBasis:" << zBasis.toString() << " origin:" << origin.toString();
+    return result.str();
+  }
+
+  /**
+   * Write the matrix to an output stream in a human readable format.
+   *
+   * \include Matrix_operator_stream.txt
+   *
+   * @since 1.0
+   */
+  friend std::ostream& operator<<(std::ostream& out, const Matrix& matrix) {
+    return out << matrix.toString();
+  }
+
+  /**
+   * The rotation and scale factors for the x-axis.
+   *
+   * \include Matrix_xBasis.txt
+   *
+   * @since 1.0
+   */
+  Vector xBasis;
+  /**
+   * The rotation and scale factors for the y-axis.
+   *
+   * \include Matrix_yBasis.txt
+   *
+   * @since 1.0
+   */
+  Vector yBasis;
+  /**
+   * The rotation and scale factors for the z-axis.
+   *
+   * \include Matrix_zBasis.txt
+   *
+   * @since 1.0
+   */
+  Vector zBasis;
+  /**
+   * The translation factors for all three axes.
+   *
+   * \include Matrix_origin.txt
+   *
+   * @since 1.0
+   */
+  Vector origin;
+};
+
+}; // namespace Leap
+
+#endif // __LeapMath_h__

BIN
engine/lib/LeapSDK/lib/libLeap.dylib


BIN
engine/lib/LeapSDK/lib/libc++/libLeap.dylib


BIN
engine/lib/LeapSDK/lib/x64/Leap.dll


BIN
engine/lib/LeapSDK/lib/x64/Leapd.dll


BIN
engine/lib/LeapSDK/lib/x64/msvcp100.dll


BIN
engine/lib/LeapSDK/lib/x64/msvcp100d.dll


BIN
engine/lib/LeapSDK/lib/x64/msvcr100.dll


BIN
engine/lib/LeapSDK/lib/x64/msvcr100d.dll


BIN
engine/lib/LeapSDK/lib/x86/Leap.dll


BIN
engine/lib/LeapSDK/lib/x86/Leap.lib


BIN
engine/lib/LeapSDK/lib/x86/Leapd.dll


BIN
engine/lib/LeapSDK/lib/x86/Leapd.lib


BIN
engine/lib/LeapSDK/lib/x86/msvcp100.dll


BIN
engine/lib/LeapSDK/lib/x86/msvcp100d.dll


BIN
engine/lib/LeapSDK/lib/x86/msvcr100.dll


BIN
engine/lib/LeapSDK/lib/x86/msvcr100d.dll


+ 7 - 7
engine/source/gui/guiCanvas.cc

@@ -31,17 +31,17 @@
 #include "gui/guiControl.h"
 #include "gui/guiCanvas.h"
 #include "game/gameInterface.h"
-
+
 #include "guiCanvas_ScriptBinding.h"
-
+
 extern int _AndroidGetScreenWidth();
 extern int _AndroidGetScreenHeight();
-
+
 
 IMPLEMENT_CONOBJECT(GuiCanvas);
 
 GuiCanvas *Canvas = NULL;
-
+
 GuiCanvas::GuiCanvas()
 {
 #ifdef TORQUE_OS_IOS
@@ -384,14 +384,14 @@ bool GuiCanvas::processInputEvent(const InputEvent *event)
 
          if (event->objType == SI_XAXIS)
          {
-            pt.x += (event->fValue * mPixelsPerMickey);
+            pt.x += (event->fValues[0] * mPixelsPerMickey);
             cursorPt.x = (F32)getMax(0, getMin((S32)pt.x, mBounds.extent.x - 1));
             if (oldpt.x != S32(cursorPt.x))
                moved = true;
          }
          else
          {
-            pt.y += (event->fValue * mPixelsPerMickey);
+            pt.y += (event->fValues[0] * mPixelsPerMickey);
             cursorPt.y = (F32)getMax(0, getMin((S32)pt.y, mBounds.extent.y - 1));
             if (oldpt.y != S32(cursorPt.y))
                moved = true;
@@ -425,7 +425,7 @@ bool GuiCanvas::processInputEvent(const InputEvent *event)
          mLastEvent.mousePoint.y = S32( cursorPt.y );
          mLastEvent.eventID = 0;
 
-            if ( event->fValue < 0.0f )
+            if ( event->fValues[0] < 0.0f )
             rootMouseWheelDown( mLastEvent );
             else
             rootMouseWheelUp( mLastEvent );

+ 536 - 255
engine/source/input/actionMap.cc

@@ -794,6 +794,11 @@ bool ActionMap::getDeviceTypeAndInstance(const char *pDeviceName, U32 &deviceTyp
       deviceType = GamepadDeviceType;
       offset     = dStrlen("gamepad");
    }
+   else if (dStrnicmp(pDeviceName, "leapdevice", dStrlen("leapdevice")) == 0)
+   {
+       deviceType = LeapMotionDeviceType;
+       offset = dStrlen("leapdevice");
+   }
    else
       return false;
     
@@ -845,7 +850,11 @@ bool ActionMap::getDeviceName(const U32 deviceType, const U32 deviceInstance, ch
 	  case GamepadDeviceType:
       dSprintf(buffer, 16, "gamepad%d", deviceInstance);
       break;
-           
+
+     case LeapMotionDeviceType:
+      dStrcpy(buffer, "leapdevice");
+      break;
+
      default:
       Con::errorf( "ActionMap::getDeviceName: unknown device type specified, %d (inst: %d)", deviceType, deviceInstance);
       return false;
@@ -1171,364 +1180,620 @@ bool ActionMap::processBind(const U32 argc, const char** argv, SimObject* object
 }
 
 //------------------------------------------------------------------------------
-bool ActionMap::processAction(const InputEvent* pEvent)
+
+bool ActionMap::processLeap(const InputEvent* pEvent)
 {
-   static const char *argv[4];
+    static const char *argv[5];
+    char buffer[64];
 
-   if (pEvent->action == SI_TOUCH) // Touches
-   {
-       static const char *args[4];
+    const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
+
+    if (pNode == NULL)
+    {
+        // Check to see if we clear the modifiers, do we find an action?
+        if (pEvent->modifier != 0)
+            pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
+
+        if (pNode == NULL)
+            return false;
+    }
+
+    // "Do nothing" bind:
+    if ( !pNode->consoleFunction[0] )
+        return( true );
+
+    argv[0] = pNode->consoleFunction;
+
+    float values[3];
+    values[0] = pEvent->fValues[0];
+    values[1] = pEvent->fValues[1];
+    values[2] = pEvent->fValues[2];
+
+    if ( pNode->flags & Node::HasDeadZone )
+    {
+        if ( pEvent->fValues[0] >= pNode->deadZoneBegin && pEvent->fValues[0] <= pNode->deadZoneEnd )
+            values[0] = 0.0f;
+        if ( pEvent->fValues[1] >= pNode->deadZoneBegin && pEvent->fValues[1] <= pNode->deadZoneEnd )
+            values[1] = 0.0f;
+        if ( pEvent->fValues[2] >= pNode->deadZoneBegin && pEvent->fValues[2] <= pNode->deadZoneEnd )
+            values[2] = 0.0f;
+
+        // All values are all null, so don't bother executing the function
+        if (!values[0] && !values[1] && !values[2])
+            return true;
+    }
+
+    switch(pEvent->objType)
+    {
+        case LM_HANDPOS:
+
+            // ID
+            argv[1] = Con::getIntArg(pEvent->iValue);
+
+            // Position
+            dSprintf(buffer, sizeof(buffer), "%f %f %f", values[0], values[1], values[2]);
+
+            argv[2] = buffer;
+
+            if (pNode->object)
+                Con::executef(pNode->object, 3, argv[0], argv[1], argv[2]);
+            else
+                Con::execute(3, argv);
+            break;
+
+        case LM_HANDROT:
+            
+            // ID
+            argv[1] = Con::getIntArg(pEvent->iValue);
+
+            // Rotation
+            dSprintf(buffer, sizeof(buffer), "%f %f %f", values[0], values[1], values[2]);
+
+            argv[2] = buffer;
+
+            if (pNode->object)
+                Con::executef(pNode->object, 3, argv[0], argv[1], argv[2]);
+            else
+                Con::execute(3, argv);
+            break;
+
+        case LM_FINGERPOS:
+            
+            // IDs
+            argv[1] = pEvent->fingerIDs;
+
+            // X-coordinates
+            argv[2] = pEvent->fingersX;
+
+            // Y-coordinates
+            argv[3] = pEvent->fingersY;
+
+            // Z-coordinates
+            argv[4] = pEvent->fingersZ;
+
+            if (pNode->object)
+                Con::executef(pNode->object, 5, argv[0], argv[1], argv[2], argv[3], argv[4]);
+            else
+                Con::execute(5, argv);
+            break;
+
+        case LM_HANDAXIS:
+        default:
+            return false;
+    }
+
+    return true;
+}
+
+//------------------------------------------------------------------------------
+
+bool ActionMap::processGesture(const InputEvent* pEvent)
+{
+    static const char *argv[6];
+    char buffer[64];
+
+    const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
+
+    if (pNode == NULL) 
+    {
+        // Check to see if we clear the modifiers, do we find an action?
+        if (pEvent->modifier != 0)
+            pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
+           
+        if (pNode == NULL)
+            return false;
+    }
+
+    // "Do nothing" bind:
+    if ( !pNode->consoleFunction[0] )
+        return( true );
+
+    // Function
+    argv[0] = pNode->consoleFunction;
+    
+    switch(pEvent->objType)
+    {
+        case SI_CIRCLE_GESTURE:
+
+            // ID
+            argv[1] = Con::getIntArg(pEvent->iValue);
+
+            // Progress
+            argv[2] = Con::getFloatArg(pEvent->fValues[0]);
+
+            // Radius
+            argv[3] = Con::getFloatArg(pEvent->fValues[1]);
+
+            // Direction (1 clockwise, 0 counter-clockwise)
+            argv[4] = Con::getFloatArg(pEvent->fValues[2]);
+
+            // State
+            argv[5] = Con::getFloatArg(pEvent->fValues[3]);
+
+            if (pNode->object)
+                Con::executef(pNode->object, 6, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
+            else
+                Con::execute(6, argv);
+            break;
+
+        case SI_SWIPE_GESTURE:
+
+            // ID
+            argv[1] = Con::getIntArg(pEvent->iValue);
+
+            // State
+            argv[2] = Con::getFloatArg(pEvent->fValues[0]);
+
+            // Direction
+            dSprintf(buffer, sizeof(buffer), "%f %f %f", pEvent->fValues[1], pEvent->fValues[2], pEvent->fValues[3]);
+
+            argv[3] = buffer;
+            // Speed
+            argv[4] = Con::getFloatArg(pEvent->fValues[4]);
+
+            if (pNode->object)
+                Con::executef(pNode->object, 5, argv[0], argv[1], argv[2], argv[3], argv[4]);
+            else
+                Con::execute(5, argv);
+            break;
+
+        case SI_KEYTAP_GESTURE:
+        case SI_SCREENTAP_GESTURE:
+
+            // ID
+            argv[1] = Con::getIntArg(pEvent->iValue);
+        
+            // Position
+            dSprintf(buffer, sizeof(buffer), "%f %f %f", pEvent->fValues[0], pEvent->fValues[1], pEvent->fValues[2]);
+
+            argv[2] = buffer;
+
+            // Direction
+            dSprintf(buffer, sizeof(buffer), "%f %f %f", pEvent->fValues[3], pEvent->fValues[4], pEvent->fValues[5]);
+
+            argv[3] = buffer;
+
+            if (pNode->object)
+                Con::executef(pNode->object, 4, argv[0], argv[1], argv[2], argv[3]);
+            else
+                Con::execute(5, argv);
+
+            break;
+
+        case SI_PINCH_GESTURE:
+        case SI_SCALE_GESTURE:
+        default:
+            return true;
+    }
        
-       const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
+    return true;
+}
+
+//------------------------------------------------------------------------------
+
+bool ActionMap::processTouch(const InputEvent* pEvent)
+{
+    static const char *argv[4];
+    const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
        
-       if (pNode == NULL) 
-       {
-           // Check to see if we clear the modifiers, do we find an action?
-           if (pEvent->modifier != 0)
-               pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
+    if (pNode == NULL) 
+    {
+        // Check to see if we clear the modifiers, do we find an action?
+        if (pEvent->modifier != 0)
+            pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
            
-           if (pNode == NULL)
-               return false;
-       }
+        if (pNode == NULL)
+            return false;
+    }
        
-       // "Do nothing" bind:
-       if ( !pNode->consoleFunction[0] )
-           return( true );
+    // "Do nothing" bind:
+    if ( !pNode->consoleFunction[0] )
+        return( true );
        
-       // Ok, we're all set up, call the function.
-       args[0] = pNode->consoleFunction;
-       args[1] = pEvent->touchIDs; //Con::getReturnBuffer(pEvent->touchIDs);
-       args[2] = pEvent->touchesX; //Con::getReturnBuffer(pEvent->touchesX);
-       args[3] = pEvent->touchesY; //Con::getReturnBuffer(pEvent->touchesY);
+    // Ok, we're all set up, call the function.
+    argv[0] = pNode->consoleFunction;
+    argv[1] = pEvent->fingerIDs;
+    argv[2] = pEvent->fingersX;
+    argv[3] = pEvent->fingersY;
        
-       if (pNode->object)
-           Con::executef(pNode->object, 2, args[0], args[1], args[2], args[3]);
-       else
-           Con::execute(4, args);
+    if (pNode->object)
+        Con::executef(pNode->object, 4, argv[0], argv[1], argv[2], argv[3]);
+    else
+        Con::execute(4, argv);
        
-       return true;
-   }
-   else if (pEvent->action == SI_MAKE) // KEYBOARD/BUTTON DOWN EVENT
-   {
-      const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
+    return true;
+}
 
-      if (pNode == NULL) 
-      {
-         // Check to see if we clear the modifiers, do we find an action?
-         if (pEvent->modifier != 0)
+//------------------------------------------------------------------------------
+
+bool ActionMap::processButton(const InputEvent* pEvent)
+{
+    static const char *argv[2];
+    const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
+
+    if (pNode == NULL) 
+    {
+        // Check to see if we clear the modifiers, do we find an action?
+        if (pEvent->modifier != 0)
             pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
 
-         if (pNode == NULL)
+        if (pNode == NULL)
             return false;
-      }
+    }
 
-      // Whadda ya know, we have this bound.  Set up, and call the console
-      //  function associated with it...
-      //
-      F32 value = pEvent->fValue;
+    // Whadda ya know, we have this bound.  Set up, and call the console
+    //  function associated with it...
+    //
+    F32 value = pEvent->fValues[0];
        
-      if (pNode->flags & Node::Ranged)
-      {
-          value = (value * 2.0f) - 1.0f;
+    if (pNode->flags & Node::Ranged)
+    {
+        value = (value * 2.0f) - 1.0f;
          
-          if (pNode->flags & Node::Inverted)
-              value *= -1.0f;
-      }
-      else
-      {
-          if (pNode->flags & Node::Inverted)
-              value = 1.0f - value;
-      }
+        if (pNode->flags & Node::Inverted)
+            value *= -1.0f;
+    }
+    else
+    {
+        if (pNode->flags & Node::Inverted)
+            value = 1.0f - value;
+    }
 
-      if (pNode->flags & Node::HasScale)
-          value *= pNode->scaleFactor;
+    if (pNode->flags & Node::HasScale)
+        value *= pNode->scaleFactor;
 
-      if (pNode->flags & Node::HasDeadZone)
-	  {
-		  if (value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd)
-             value = 0.0f;
-		  else			
-         {
+    if (pNode->flags & Node::HasDeadZone)
+    {
+        if (value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd)
+            value = 0.0f;
+        else			
+        {
             if( value > 0 )
-               value = ( value - pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
+                value = ( value - pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
             else
-               value = ( value + pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
-         }
-	  }
+                value = ( value + pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
+        }
+    }
 
-	   if( pNode->flags & Node::NonLinear )
-         value = ( value < 0.f ? -1.f : 1.f ) * mPow( mFabs( value ), CONST_E );
+    if( pNode->flags & Node::NonLinear )
+        value = ( value < 0.f ? -1.f : 1.f ) * mPow( mFabs( value ), CONST_E );
 
-      // Ok, we're all set up, call the function.
-      if(pNode->flags & Node::BindCmd)
-      {
-         // it's a bind command
-         if(pNode->makeConsoleCommand)
+    // Ok, we're all set up, call the function.
+    if(pNode->flags & Node::BindCmd)
+    {
+        // it's a bind command
+        if(pNode->makeConsoleCommand)
             Con::evaluate(pNode->makeConsoleCommand);
-      }
-      else if ( pNode->consoleFunction[0] )
-      {
-         argv[0] = pNode->consoleFunction;
-         argv[1] = Con::getFloatArg(value);
-         if (pNode->object)
+    }
+    else if ( pNode->consoleFunction[0] )
+    {
+        argv[0] = pNode->consoleFunction;
+        argv[1] = Con::getFloatArg(value);
+        
+        if (pNode->object)
             Con::executef(pNode->object, 2, argv[0], argv[1]);
-         else
+        else
             Con::execute(2, argv);
-      }
+    }
 
-      // [neo, 5/13/2007 - #3109]
-      // The execs/evaluate above could have called reentrant script code which made calls to
-      // bindCmd() etc, channging the node map underneath us. If enough nodes were added then
-      // the node map vector would realloc, with the result that pNode would then be pointing 
-      // at garbage and cause a crash when passed to enterBreakEvent() below. So we just look
-      // it up again to be safe. This is not needed in the other cases below as we return right
-      // after the execs and don't use pNode again.
-      pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst );
+    // [neo, 5/13/2007 - #3109]
+    // The execs/evaluate above could have called reentrant script code which made calls to
+    // bindCmd() etc, channging the node map underneath us. If enough nodes were added then
+    // the node map vector would realloc, with the result that pNode would then be pointing 
+    // at garbage and cause a crash when passed to enterBreakEvent() below. So we just look
+    // it up again to be safe. This is not needed in the other cases below as we return right
+    // after the execs and don't use pNode again.
+    pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst );
 
-      if( pNode == NULL )
-         return true; // We already called any bound methods/functions so our job is done
+    if( pNode == NULL )
+        return true; // We already called any bound methods/functions so our job is done
 
-      //
-      // And enter the break into the table if this is a make event...
-      enterBreakEvent(pEvent, pNode);
+    //
+    // And enter the break into the table if this is a make event...
+    enterBreakEvent(pEvent, pNode);
 
-      return true;
-   } 
-   else if (pEvent->action == SI_MOVE) // MOUSE/JOYSTICK MOVE EVENT
-   {
-      if (pEvent->deviceType == MouseDeviceType)
-      {
-         const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType);
+    return true;
+}
 
-         if (pNode == NULL)
-         {
+//------------------------------------------------------------------------------
+
+bool ActionMap::processMove(const InputEvent* pEvent)
+{
+    static const char *argv[2];
+
+    if (pEvent->deviceType == MouseDeviceType)
+    {
+        const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType);
+
+        if (pNode == NULL)
+        {
             // Check to see if we clear the modifiers, do we find an action?
             if (pEvent->modifier != 0)
-               pNode = findNode(pEvent->deviceType, pEvent->deviceInst,
-                                0,                  pEvent->objType);
+                pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objType);
 
             if (pNode == NULL)
-               return false;
-         }
+                return false;
+        }
 
-         // "Do nothing" bind:
-         if ( !pNode->consoleFunction[0] )
+        // "Do nothing" bind:
+        if ( !pNode->consoleFunction[0] )
             return( true );
 
-         // Whadda ya know, we have this bound.  Set up, and call the console
-         //  function associated with it.  Mouse events ignore range and dead
-         //  zone params.
-         //
-         F32 value = pEvent->fValue;
+        // Whadda ya know, we have this bound.  Set up, and call the console
+        //  function associated with it.  Mouse events ignore range and dead
+        //  zone params.
+        //
+        F32 value = pEvent->fValues[0];
          
-         if (pNode->flags & Node::Inverted)
+        if (pNode->flags & Node::Inverted)
             value *= -1.0f;
-         if (pNode->flags & Node::HasScale)
+        if (pNode->flags & Node::HasScale)
             value *= pNode->scaleFactor;
 
-         // Ok, we're all set up, call the function.
-         argv[0] = pNode->consoleFunction;
-         argv[1] = Con::getFloatArg(value);
+        // Ok, we're all set up, call the function.
+        argv[0] = pNode->consoleFunction;
+        argv[1] = Con::getFloatArg(value);
           
-         if (pNode->object)
+        if (pNode->object)
             Con::executef(pNode->object, 2, argv[0], argv[1]);
-         else
+        else
             Con::execute(2, argv);
 
-         return true;
-      } 
-       else if ( (pEvent->objType == XI_POS || pEvent->objType == XI_FLOAT || pEvent->objType == XI_ROT || pEvent->objType == XI_INT) )
-      {
-         const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst,
-                                      pEvent->modifier,   pEvent->objInst);
+            return true;
+    } 
+    else if ( (pEvent->objType == XI_POS || pEvent->objType == XI_FLOAT || pEvent->objType == XI_ROT || pEvent->objType == XI_INT) )
+    {
+        const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier,   pEvent->objInst);
 
-         if( pNode == NULL )
+        if( pNode == NULL )
             return false;
 
-         // Ok, we're all set up, call the function.
-         argv[0] = pNode->consoleFunction;
-         S32 argc = 1;
+        // Ok, we're all set up, call the function.
+        argv[0] = pNode->consoleFunction;
+        S32 argc = 1;
 
-         if (pEvent->objType == XI_INT)
-         {
+        if (pEvent->objType == XI_INT)
+        {
             // Handle the integer as some sort of motion such as a
             // single component to an absolute position
             argv[1] = Con::getIntArg( pEvent->iValue );
             argc += 1;
-         }
-         else if (pEvent->objType == XI_FLOAT)
-         {
+        }
+        else if (pEvent->objType == XI_FLOAT)
+        {
             // Handle float as some sort of motion such as a
             // single component to an absolute position
-            argv[1] = Con::getFloatArg( pEvent->fValue );
+            argv[1] = Con::getFloatArg( pEvent->fValues[0] );
             argc += 1;
-         }
-         else if (pEvent->objType == XI_POS)
-         {
+        }
+        else if (pEvent->objType == XI_POS)
+        {
             // Handle Point3F type position
-            argv[1] = Con::getFloatArg( pEvent->fValue );
-            argv[2] = Con::getFloatArg( pEvent->fValue2 );
-            argv[3] = Con::getFloatArg( pEvent->fValue3 );
+            argv[1] = Con::getFloatArg( pEvent->fValues[0] );
+            argv[2] = Con::getFloatArg( pEvent->fValues[1] );
+            argv[3] = Con::getFloatArg( pEvent->fValues[2] );
 
             argc += 3;
-         }
+        }
 
-         if (pNode->object)
-         {
+        if (pNode->object)
+        {
             Con::execute(pNode->object, argc, argv);
-         }
-         else
-         {
+        }
+        else
+        {
             Con::execute(argc, argv);
-         }
+        }
 
-         return true;
-      }
-	    else if ( pEvent->deviceType == JoystickDeviceType || pEvent->deviceType == GamepadDeviceType )
-      {
-         // Joystick events...
-         const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst,
-                                       pEvent->modifier,   pEvent->objInst );
+        return true;
+    }
+    else if ( pEvent->deviceType == JoystickDeviceType || pEvent->deviceType == GamepadDeviceType )
+    {
+        // Joystick events...
+        const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier,   pEvent->objInst );
 
-         if( pNode == NULL )
+        if( pNode == NULL )
             return false;
 
-         // "Do nothing" bind:
-         if ( !pNode->consoleFunction[0] )
+        // "Do nothing" bind:
+        if ( !pNode->consoleFunction[0] )
             return( true );
 
-         // Whadda ya know, we have this bound.  Set up, and call the console
-         //  function associated with it.  Joystick move events are the same as mouse
-         //  move events except that they don't ignore dead zone.
-         //
-         F32 value = pEvent->fValue;
-         if ( pNode->flags & Node::Inverted )
+        // Whadda ya know, we have this bound.  Set up, and call the console
+        //  function associated with it.  Joystick move events are the same as mouse
+        //  move events except that they don't ignore dead zone.
+        //
+        F32 value = pEvent->fValues[0];
+        if ( pNode->flags & Node::Inverted )
             value *= -1.0f;
 
-         if ( pNode->flags & Node::HasScale )
+        if ( pNode->flags & Node::HasScale )
             value *= pNode->scaleFactor;
 
-         if ( pNode->flags & Node::HasDeadZone )
-         {
-            if ( value >= pNode->deadZoneBegin &&
-                 value <= pNode->deadZoneEnd )
-               value = 0.0f;
+        if ( pNode->flags & Node::HasDeadZone )
+        {
+            if ( value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd )
+            {
+                value = 0.0f;
+            }
             else
             {
-               if( value > 0 )
-                  value = ( value - pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
-               else
-                  value = ( value + pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
+                if( value > 0 )
+                    value = ( value - pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
+                else
+                    value = ( value + pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
             }
-         }
+        }
 
-         if( pNode->flags & Node::NonLinear )
+        if( pNode->flags & Node::NonLinear )
             value = ( value < 0.f ? -1.f : 1.f ) * mPow( mFabs( value ), CONST_E );
 
-         // Ok, we're all set up, call the function.
-         argv[0] = pNode->consoleFunction;
-         argv[1] = Con::getFloatArg( value );
-         if (pNode->object)
+        // Ok, we're all set up, call the function.
+        argv[0] = pNode->consoleFunction;
+        argv[1] = Con::getFloatArg( value );
+            
+        if (pNode->object)
             Con::executef(pNode->object, S32(argv[0]), argv[1]);
-         else
+        else
             Con::execute(2, argv);
 
-         return true;
-      }
-   }
-   else if (pEvent->action == SI_MOTION) // iOS MOTION EVENT
-   {
-       // iOS Accelerometer, Gyroscope and DeviceMotion processing
-       // Currently, this is identical to the joystick handling.
+        return true;
+    }
+
+    return false;
+}
+
+//------------------------------------------------------------------------------
+
+bool ActionMap::processMotion(const InputEvent* pEvent)
+{
+    static const char *argv[2];
+
+    // iOS Accelerometer, Gyroscope and DeviceMotion processing
+    // Currently, this is identical to the joystick handling.
        
-       // This was copied over into its own section because this will
-       // give us a dedicated section to tweak processing based on iOS specific
-       // devices. No point in trying to mangle joystick code any further
-       const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier,   pEvent->objType );
+    // This was copied over into its own section because this will
+    // give us a dedicated section to tweak processing based on iOS specific
+    // devices. No point in trying to mangle joystick code any further
+    const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier,   pEvent->objType );
        
-       if ( pNode == NULL )
-       {
-           // Check to see if we clear the modifiers, do we find an action?
-           if (pEvent->modifier != 0)
-               pNode = findNode( pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objType );
+    if ( pNode == NULL )
+    {
+        // Check to see if we clear the modifiers, do we find an action?
+        if (pEvent->modifier != 0)
+            pNode = findNode( pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objType );
            
-           if ( pNode == NULL )
-               return false;
-       }
+        if ( pNode == NULL )
+            return false;
+    }
        
-       // "Do nothing" bind:
-       if ( !pNode->consoleFunction[0] )
-           return( true );
+    // "Do nothing" bind:
+    if ( !pNode->consoleFunction[0] )
+        return( true );
        
-       F32 value = pEvent->fValue;
+    F32 value = pEvent->fValues[0];
        
-       if ( pNode->flags & Node::Inverted )
-           value *= -1.0f;
+    if ( pNode->flags & Node::Inverted )
+        value *= -1.0f;
        
-       if ( pNode->flags & Node::HasScale )
-           value *= pNode->scaleFactor;
+    if ( pNode->flags & Node::HasScale )
+        value *= pNode->scaleFactor;
        
-       if ( pNode->flags & Node::HasDeadZone )
-           if ( value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd )
-               value = 0.0f;
+    if ( pNode->flags & Node::HasDeadZone )
+    {
+        if ( value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd )
+            value = 0.0f;
+    }
        
-       // Ok, we're all set up, call the function.
-       argv[0] = pNode->consoleFunction;
-       argv[1] = Con::getFloatArg( value );
+    // Ok, we're all set up, call the function.
+    argv[0] = pNode->consoleFunction;
+    argv[1] = Con::getFloatArg( value );
        
-       if (pNode->object)
-           Con::executef(pNode->object, 2, argv[0], argv[1]);
-       else
-           Con::execute(2, argv);
+    if (pNode->object)
+        Con::executef(pNode->object, 2, argv[0], argv[1]);
+    else
+        Con::execute(2, argv);
        
-       return true;
-   }
-   else if (pEvent->action == SI_BREAK) // UP EVENT
-   {
-      return checkBreakTable(pEvent);
-   }
-      else if (pEvent->action == SI_VALUE)
-   {
-      if ( (pEvent->objType == XI_FLOAT || pEvent->objType == XI_INT) )
-      {
-         const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst,
-                                      pEvent->modifier,   pEvent->objInst);
+    return true;
+}
+
+//------------------------------------------------------------------------------
+
+bool ActionMap::processXInput(const InputEvent* pEvent)
+{
+    static const char *argv[2];
+
+    if ((pEvent->objType == XI_FLOAT || pEvent->objType == XI_INT))
+    {
+        const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
 
-         if( pNode == NULL )
+        if (pNode == NULL )
             return false;
 
-         // Ok, we're all set up, call the function.
-         argv[0] = pNode->consoleFunction;
-         S32 argc = 1;
+        // Ok, we're all set up, call the function.
+        argv[0] = pNode->consoleFunction;
+        S32 argc = 1;
 
-         if (pEvent->objType == XI_INT)
-         {
+        if (pEvent->objType == XI_INT)
+        {
             // Handle the integer as some sort of motion such as a
             // single component to an absolute position
             argv[1] = Con::getIntArg( pEvent->iValue );
             argc += 1;
-         }
-         else if (pEvent->objType == XI_FLOAT)
-         {
+        }
+        else if (pEvent->objType == XI_FLOAT)
+        {
             // Handle float as some sort of motion such as a
             // single component to an absolute position
-            argv[1] = Con::getFloatArg( pEvent->fValue );
+            argv[1] = Con::getFloatArg( pEvent->fValues[0] );
             argc += 1;
-         }
+        }
 
-         if (pNode->object)
-         {
+        if (pNode->object)
+        {
             Con::execute(pNode->object, argc, argv);
-         }
-         else
-         {
+        }
+        else
+        {
             Con::execute(argc, argv);
-         }
+        }
+    }
+    
+    return true;
+}
 
-         return true;
-      }
-   }
-   return false;
+//------------------------------------------------------------------------------
+
+bool ActionMap::processAction(const InputEvent* pEvent)
+{
+    switch(pEvent->action)
+    {
+    case SI_LEAP:
+        return processLeap(pEvent);
+        break;
+    case SI_GESTURE:
+        return processGesture(pEvent);
+        break;
+    case SI_TOUCH:
+        return processTouch(pEvent);
+        break;
+    case SI_MAKE:
+        return processButton(pEvent);
+        break;
+    case SI_MOVE:
+        return processMove(pEvent);
+        break;
+    case SI_MOTION:
+        return processMotion(pEvent);
+        break;
+    case SI_BREAK:
+        return checkBreakTable(pEvent);
+        break;
+    case SI_VALUE:
+        return processXInput(pEvent);
+    }
+
+    return false;
 }
 
 //------------------------------------------------------------------------------
@@ -1590,7 +1855,7 @@ bool ActionMap::checkBreakTable(const InputEvent* pEvent)
           smBreakTable[i].objInst    == U32(pEvent->objInst)) {
          // Match.  Issue the break event...
          //
-         F32 value = pEvent->fValue;
+         F32 value = pEvent->fValues[0];
          if (smBreakTable[i].flags & Node::Ranged) {
             value = (value * 2.0f) - 1.0f;
             if (smBreakTable[i].flags & Node::Inverted)
@@ -1903,14 +2168,30 @@ CodeMapping gVirtualMap[] =
    { "pitch",         SI_MOTION,    SI_PITCH     },
    { "roll",          SI_MOTION,    SI_ROLL      },
 
+   //-------------------------------------- TOUCH EVENTS
+   // Touch events:
    { "touchdown",     SI_TOUCH,    SI_TOUCHDOWN  },
    { "touchup",       SI_TOUCH,    SI_TOUCHUP    },
    { "touchmove",     SI_TOUCH,    SI_TOUCHMOVE  },
-   { "gesture",       SI_TOUCH,    SI_GESTURE    },
 
+   //-------------------------------------- GESTURE EVENTS
+   // Preset gesture events:
+   { "circleGesture",      SI_GESTURE,  SI_CIRCLE_GESTURE    },
+   { "swipeGesture",       SI_GESTURE,  SI_SWIPE_GESTURE     },
+   { "screenTapGesture",   SI_GESTURE,  SI_SCREENTAP_GESTURE },
+   { "keyTapGesture",      SI_GESTURE,  SI_KEYTAP_GESTURE    },
+   { "pinchGesture",       SI_GESTURE,  SI_PINCH_GESTURE     },
+   { "scaleGesture",       SI_GESTURE,  SI_SCALE_GESTURE     },
+
+   //-------------------------------------- GESTURE EVENTS
+   // Preset gesture events:
+   { "leapHandAxis",    SI_LEAP,     LM_HANDAXIS    },
+   { "leapHandPos",     SI_LEAP,     LM_HANDPOS     },
+   { "leapHandRot",     SI_LEAP,     LM_HANDROT     },
+   { "leapFingerPos",   SI_LEAP,     LM_FINGERPOS   },
+   
    //-------------------------------------- MISCELLANEOUS EVENTS
    //
-
    { "anykey",        SI_KEY,      KEY_ANYKEY },
    { "nomatch",       SI_UNKNOWN,  0xFFFFFFFF }
 };

+ 9 - 2
engine/source/input/actionMap.h

@@ -23,6 +23,7 @@
 #ifndef _ACTIONMAP_H_
 #define _ACTIONMAP_H_
 
+
 #ifndef _PLATFORM_H_
 #include "platform/platform.h"
 #endif
@@ -165,8 +166,14 @@ class ActionMap : public SimObject
    static const char* buildActionString( const InputEvent* event );
 
    bool processAction(const InputEvent*);
-
-   static bool checkBreakTable(const InputEvent*);
+   bool processLeap(const InputEvent*);
+   bool processGesture(const InputEvent*);
+   bool processTouch(const InputEvent*);
+   bool processButton(const InputEvent*);
+   bool processMove(const InputEvent*);
+   bool processMotion(const InputEvent*);
+   bool processXInput(const InputEvent*);
+   static bool checkBreakTable(const InputEvent*);   
    static bool handleEvent(const InputEvent*);
    static bool handleEventGlobal(const InputEvent*);
 

+ 176 - 0
engine/source/input/leapMotion/LeapMotionManager_ScriptBinding.h

@@ -0,0 +1,176 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+ConsoleFunction(initLeapMotionManager, void, 1, 1, "() Initialize the LeapMotionManager")
+{
+    if (gLeapMotionManager != NULL)
+    {
+        Con::printf("LeapMotionManager already initialized");
+    }
+    else
+    {
+        gLeapMotionManager = new LeapMotionManager();
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleFunction(enableLeapMotionManager, void, 2, 2, "(bool enabledState) Run or pause the LeapMotionManager.\n"
+                                                     "@param enabledState True to turn it on, false otherwise")
+{
+    if (gLeapMotionManager == NULL)
+    {
+        Con::printf("LeapMotionManager not initialized. Call initLeapMotionManager() first");
+    }
+    else
+    {
+        gLeapMotionManager->enable(dAtob(argv[1]));
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleFunction(isLeapMotionManagerEnabled, bool, 1, 1, "() Checks the LeapMotionManager to see if it is enabled.\n"
+                                                        "@return True if it's running, false otherwise")
+{
+    if (gLeapMotionManager == NULL)
+    {
+        Con::printf("LeapMotionManager not initialized. Call initLeapMotionManager() first");
+        return false;
+    }
+    else
+    {
+        return gLeapMotionManager->getEnabled();
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleFunction(enableLeapCursorControl, void, 2, 2, "(bool enabledState) Toggles the manager to act like a mouse.\n"
+                                                        "@param enabledState True to act like a mouse, false otherwise")
+{
+    if (gLeapMotionManager == NULL)
+    {
+        Con::printf("LeapMotionManager not initialized. Call initLeapMotionManager() first");
+    }
+    else
+    {
+        return gLeapMotionManager->toggleMouseControl(dAtob(argv[1]));
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleFunction(isLeapCursorControlled, bool, 1, 1, "() Checks the LeapMotionManager to see if it is controlling the mouse.\n"
+        "@return True if it's acting as a mouse, false otherwise")
+{
+    if (gLeapMotionManager == NULL)
+    {
+        Con::printf("LeapMotionManager not initialized. Call initLeapMotionManager() first");
+        return false;
+    }
+    else
+    {
+        return gLeapMotionManager->getMouseControlToggle();
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleFunction(configureLeapGesture, bool, 3, 3,   "(gestureString, value) Modified a Config string on the main "
+                                                    "Controller, via the LeapMotionManager. The following strings are allowed:\n"
+                                                    "Gesture.Circle.MinProgress\n"
+                                                    "Gesture.Circle.MinRadius\n"
+                                                    "Gesture.Circle.MinArc\n"
+                                                    "Gesture.Swipe.MinLength\n"
+                                                    "Gesture.Swipe.MinVelocity\n"
+                                                    "Gesture.KeyTap.MinDownVelocity\n"
+                                                    "Gesture.KeyTap.HistorySeconds\n"
+                                                    "Gesture.KeyTap.MinDistance\n"
+                                                    "Gesture.ScreenTap.MinForwardVelocity\n"
+                                                    "Gesture.ScreenTap.HistorySeconds\n"
+                                                    "Gesture.ScreenTap.MinDistance\n"
+                                                    "@param gestureString The Config string to be set\n"
+                                                    "@param value The new value for the Config string\n"
+                                                    "@return True if string was successfully set, false otherwise")
+{
+    if (gLeapMotionManager == NULL)
+    {
+        Con::printf("LeapMotionManager not initialized. Call initLeapMotionManager() first");
+        return false;
+    }
+    else
+    {
+        if (!dStrcmp("Gesture.Circle.MinProgress", argv[1]))
+        {
+            return gLeapMotionManager->setMinCircleProgress(dAtof(argv[2]));
+        }
+        else
+        {
+            return gLeapMotionManager->configureLeapGesture(argv[1], dAtof(argv[2]));
+        }
+    }
+}
+
+ConsoleFunction(getPointFromProjection, const char*, 2, 4, "(x, y, z) - Gets the closest point on the screen to a point in space using Leap::Screen::project().\n"
+                                                             "@param x The x component of the finger position.\n"
+                                                             "@param y The y component of the finger position.\n"
+                                                             "@param z The z component of the finger position.\n\n"
+                                                             "@return An \"x y\" position of where the finger intersects with the screen.")
+{
+    // The new position.
+    Point3F pos;
+
+    if(argc == 2)
+    {
+        dSscanf(argv[1], "%g %g %g", &pos.x, &pos.y, &pos.z);
+    }
+    else if (argc == 4)
+    {
+        pos.x = dAtof(argv[1]);
+        pos.y = dAtof(argv[2]);
+        pos.z = dAtof(argv[3]);
+    }
+    else
+    {
+        Con::warnf("getPointFromProjection() - Invalid number of parameters!");
+        return "";
+    }
+
+   return gLeapMotionManager->getPointFromProjection(pos).scriptThis();
+   
+   
+}
+
+ConsoleFunction(getPointFromIntersection, const char*, 2, 2, "(fingerID) - Gets the point of intersection between the screen and a ray "
+                                                             "projected from a Pointable object using the Screen::intersect() function\n"
+                                                             "@param fingerID The finger ID, which will be grabbed from the last frame.\n\n"
+                                                             "@return An \"x y\" position of where the finger intersects with the screen.")
+{
+    if(argc < 2)
+    {
+        Con::warnf("getPointFromIntersection() - Invalid number of parameters!");
+        return "";
+    }
+
+    return gLeapMotionManager->getPointFromIntersection(dAtoi(argv[1])).scriptThis();
+}

+ 35 - 0
engine/source/input/leapMotion/leapMotionConstants.h

@@ -0,0 +1,35 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _LEAPMOTIONCONSTANTS_H_
+#define _LEAPMOTIONCONSTANTS_H_
+
+namespace LeapMotionConstants
+{
+    enum Constants
+    {
+        MaxHands             = 2,
+        MaxPointablesPerHand = 5,
+    };
+}
+
+#endif   // _LEAPMOTIONCONSTANTS_H_

+ 674 - 0
engine/source/input/leapMotion/leapMotionManager.cc

@@ -0,0 +1,674 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _LEAPMOTIONMANAGER_H_
+#include "input/leapMotion/leapMotionManager.h"
+#endif
+
+#ifndef _PLATFORM_MEMORY_H_
+#include "platform/platformMemory.h"
+#endif 
+
+#ifndef _CONSOLETYPES_H_
+#include "console/consoleTypes.h"
+#endif
+
+#ifndef _EVENT_H_
+#include "platform/event.h"
+#endif
+
+#ifndef _GAMEINTERFACE_H_
+#include "game/gameInterface.h"
+#endif
+
+#ifndef _GUICANVAS_H_
+#include "gui/guiCanvas.h"
+#endif
+
+#ifndef _LEAPMOTIONUTIL_H_
+#include "leapMotionUtil.h"
+#endif
+
+#ifndef _VECTOR2_H_
+#include "2d/core/Vector2.h"
+#endif
+
+#include "input/leapMotion/LeapMotionManager_ScriptBinding.h"
+
+//-----------------------------------------------------------------------------
+
+bool LeapMotionManager::smEnableDevice = true;
+
+bool LeapMotionManager::smGenerateIndividualEvents = true;
+bool LeapMotionManager::smKeepHandIndexPersistent = false;
+bool LeapMotionManager::smKeepPointableIndexPersistent = false;
+
+bool LeapMotionManager::smGenerateSingleHandRotationAsAxisEvents = false;
+
+F32 LeapMotionManager::smMaximumHandAxisAngle = 25.0f;
+
+bool LeapMotionManager::smGenerateWholeFrameEvents = false;
+
+U32 LeapMotionManager::LM_FRAMEVALIDDATA = 0;
+U32 LeapMotionManager::LM_HAND[LeapMotionConstants::MaxHands] = {0};
+//U32 LeapMotionManager::LM_HANDROT[LeapMotionConstants::MaxHands] = {0};
+U32 LeapMotionManager::LM_HANDAXISX = 0;
+U32 LeapMotionManager::LM_HANDAXISY = 0;
+U32 LeapMotionManager::LM_HANDPOINTABLE[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand] = {0};
+U32 LeapMotionManager::LM_HANDPOINTABLEROT[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand] = {0};
+U32 LeapMotionManager::LM_FRAME = 0;
+
+//-----------------------------------------------------------------------------
+
+LeapMotionManager::LeapMotionManager()
+{
+    // Initialize the console variables
+    staticInit();
+
+    // Create our controller and listener
+    mListener = new MotionListener();
+    mController = new Leap::Controller();
+    mController->addListener(*mListener);
+
+    // Allocate a mutex to use later
+    mActiveMutex = Mutex::createMutex();
+
+    // Nothing is ready yet
+    mEnabled = false;
+    mActive = false;
+    mMouseControl = false;
+    mMinCircleProgress = 0.0;
+}
+
+//-----------------------------------------------------------------------------
+
+LeapMotionManager::~LeapMotionManager()
+{
+    // Disable and delete internal members
+    disable();
+
+    // Get rid of the mutex
+    Mutex::destroyMutex(mActiveMutex);
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::staticInit()
+{
+    // If true, the Leap Motion device will be enabled, if present
+    Con::addVariable("pref::LeapMotion::EnableDevice", TypeBool, &smEnableDevice);
+   
+    // Indicates that events for each hand and pointable will be created.
+    Con::addVariable("LeapMotion::GenerateIndividualEvents", TypeBool, &smGenerateIndividualEvents);
+      
+	// Indicates that we track hand IDs and will ensure that the same hand will remain at the same index between frames.   
+    Con::addVariable("LeapMotion::KeepHandIndexPersistent", TypeBool, &smKeepHandIndexPersistent);
+    
+	// Indicates that we track pointable IDs and will ensure that the same pointable will remain at the same index between frames.   
+    Con::addVariable("LeapMotion::KeepPointableIndexPersistent", TypeBool, &smKeepPointableIndexPersistent);
+    
+	// If true, broadcast single hand rotation as axis events.
+    Con::addVariable("LeapMotion::GenerateSingleHandRotationAsAxisEvents", TypeBool, &smGenerateSingleHandRotationAsAxisEvents);
+    
+	// The maximum hand angle when used as an axis event as measured from a vector pointing straight up (in degrees).
+    // Shoud range from 0 to 90 degrees.   
+    Con::addVariable("LeapMotion::MaximumHandAxisAngle", TypeF32, &smMaximumHandAxisAngle);
+    
+    // Indicates that a whole frame event should be generated and frames should be buffered.
+    Con::addVariable("LeapMotion::GenerateWholeFrameEvents", TypeBool, &smGenerateWholeFrameEvents);   
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::enable(bool enabledState)
+{
+    Mutex::lockMutex(mActiveMutex);
+    mEnabled = enabledState;
+    Mutex::unlockMutex(mActiveMutex);
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::disable()
+{
+    if (mController)
+    {
+        delete mController;
+        mController = NULL;
+
+        if (mListener)
+        {
+            delete mListener;
+            mListener = NULL;
+        }
+    }
+
+    setActive(false);
+    mEnabled = false;
+}
+
+//-----------------------------------------------------------------------------
+
+bool LeapMotionManager::getActive()
+{
+    Mutex::lockMutex(mActiveMutex);
+    bool active = mActive;
+    Mutex::unlockMutex(mActiveMutex);
+
+    return active;
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::setActive(bool state)
+{
+    Mutex::lockMutex(mActiveMutex);
+    mActive = state;
+    Mutex::unlockMutex(mActiveMutex);
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::toggleMouseControl(bool enabledState)
+{
+    Mutex::lockMutex(mActiveMutex);
+    mMouseControl = enabledState;
+    Mutex::unlockMutex(mActiveMutex);
+}
+
+//-----------------------------------------------------------------------------
+
+bool LeapMotionManager::getMouseControlToggle()
+{
+    Mutex::lockMutex(mActiveMutex);
+    bool mouseControlled = mMouseControl;
+    Mutex::unlockMutex(mActiveMutex);
+
+    return mouseControlled;
+}
+
+//-----------------------------------------------------------------------------
+// You can get and set gesture configuration parameters using the Config object
+// obtained from a connected Controller object. The key strings required to
+// * identify a configuration parameter include:
+//*
+//* Key string | Value type | Default value | Units
+//* -----------|------------|---------------|------
+//* Gesture.Circle.MinRadius | float | 5.0 | mm
+//* Gesture.Circle.MinArc | float | 1.5 | radians
+//* Gesture.Swipe.MinLength | float | 150 | mm
+//* Gesture.Swipe.MinVelocity | float | 1000 | mm/s
+//* Gesture.KeyTap.MinDownVelocity | float | 50 | mm/s
+//* Gesture.KeyTap.HistorySeconds | float | 0.1 | s
+//* Gesture.KeyTap.MinDistance | float | 3.0 | mm
+//* Gesture.ScreenTap.MinForwardVelocity  | float | 50 | mm/s
+//* Gesture.ScreenTap.HistorySeconds | float | 0.1 | s
+//* Gesture.ScreenTap.MinDistance | float | 5.0 | mm
+bool LeapMotionManager::configureLeapGesture(const char* configString, const F32 value)
+{
+    // Get this controller's config.
+    Leap::Config config = mController->config();
+    
+    // Convert and pass the key, along with the value.
+    std::string *keyString = new std::string(configString);
+    bool success = config.setFloat(*keyString, value);
+    
+    // Free memory and return the result.
+    delete keyString;
+    return success;
+}
+
+//-----------------------------------------------------------------------------
+
+bool LeapMotionManager::setMinCircleProgress(const F32 value)
+{
+    mMinCircleProgress = value;
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::processHand(const Leap::Hand& hand, S32 id)
+{
+    // Get hand (palm) position
+    /*Point3F rawHandPosition;
+    Point3I convertedHandPosition;
+    
+    LeapMotionUtil::convertPosition(hand.palmPosition(), rawHandPosition);
+    convertedHandPosition.x = (S32)mFloor(rawHandPosition.x);
+    convertedHandPosition.y = (S32)mFloor(rawHandPosition.y);
+    convertedHandPosition.z = (S32)mFloor(rawHandPosition.z);*/
+
+    // Get the hand's normal vector and direction
+    const Leap::Vector normal = hand.palmNormal();
+    const Leap::Vector direction = hand.direction();
+
+    F32 pitch = direction.pitch() * Leap::RAD_TO_DEG;
+    F32 roll = normal.roll() * Leap::RAD_TO_DEG;
+    F32 yaw = direction.yaw() * Leap::RAD_TO_DEG;
+
+    // Position Event
+    InputEvent handPosEvent;
+
+    handPosEvent.deviceInst = 0;
+    handPosEvent.iValue = id;
+    handPosEvent.fValues[0] = hand.palmPosition().x;
+    handPosEvent.fValues[1] = hand.palmPosition().y;
+    handPosEvent.fValues[2] = hand.palmPosition().z;
+    handPosEvent.deviceType = LeapMotionDeviceType;
+    handPosEvent.objType = LM_HANDPOS;
+    handPosEvent.objInst = 0;
+    handPosEvent.action = SI_LEAP;
+    handPosEvent.modifier = 0;
+
+    InputEvent handRotEvent;
+
+    handRotEvent.deviceInst = 0;
+    handRotEvent.iValue = id;
+    handRotEvent.fValues[0] = yaw;
+    handRotEvent.fValues[1] = pitch;
+    handRotEvent.fValues[2] = roll;
+    handRotEvent.objType = LM_HANDROT;
+    handRotEvent.deviceType = LeapMotionDeviceType;
+    handRotEvent.objInst = 0;
+    handRotEvent.action = SI_LEAP;
+    handRotEvent.modifier = 0;
+
+    Game->postEvent(handPosEvent);
+    Game->postEvent(handRotEvent);
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::processHandPointables(const Leap::PointableList& pointables)
+{
+    InputEvent pointablePositionEvent;
+    pointablePositionEvent.deviceInst = 0;
+    pointablePositionEvent.objInst = 0;
+    pointablePositionEvent.modifier = 0;
+    pointablePositionEvent.deviceType = LeapMotionDeviceType;
+    pointablePositionEvent.objType = LM_FINGERPOS;    
+    pointablePositionEvent.action = SI_LEAP;
+    
+    for (int f = 0; f < pointables.count(); ++f)
+    {
+        Leap::Pointable pointable = pointables[f];
+        
+        char charHolder[10];
+        Leap::Vector tipPosition = pointables[f].tipPosition();
+
+        dItoa((S32)tipPosition.x, charHolder);
+        dStrcat(pointablePositionEvent.fingersX, charHolder);
+        dStrcat(pointablePositionEvent.fingersX, " ");
+
+        dItoa((S32)tipPosition.y, charHolder);
+        dStrcat(pointablePositionEvent.fingersY, charHolder);
+        dStrcat(pointablePositionEvent.fingersY, " ");
+
+        dItoa((S32)tipPosition.z, charHolder);
+        dStrcat(pointablePositionEvent.fingersZ, charHolder);
+        dStrcat(pointablePositionEvent.fingersZ, " ");
+
+        dItoa(pointables[f].id(), charHolder);
+        dStrcat(pointablePositionEvent.fingerIDs, charHolder);
+        dStrcat(pointablePositionEvent.fingerIDs, " ");        
+    }
+    
+    // Post
+    Game->postEvent(pointablePositionEvent);
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::processGestures(const Leap::GestureList& gestures)
+{
+    for (int g = 0; g < gestures.count(); ++g)
+    {
+        Leap::Gesture gesture = gestures[g];
+
+        switch (gesture.type())
+        {
+            case Leap::Gesture::TYPE_CIRCLE:
+            {
+                Leap::CircleGesture circle = gesture;
+
+                if (circle.progress() < mMinCircleProgress)
+                    break;
+
+                bool clockWise;
+
+                if (circle.pointable().direction().angleTo(circle.normal()) <= Leap::PI/4) 
+                    clockWise = true;
+                else 
+                    clockWise = false;
+
+                InputEvent event;
+            
+                event.deviceInst = 0;
+                event.iValue = g;
+                event.fValues[0] = circle.progress();
+                event.fValues[1] = circle.radius();
+                event.fValues[2] = clockWise;
+                event.fValues[3] = (F32)circle.state();
+                event.deviceType = LeapMotionDeviceType;
+                event.objType = SI_CIRCLE_GESTURE;
+                event.objInst = 0;
+                event.action = SI_GESTURE;
+                event.modifier = 0;
+            
+                Game->postEvent(event);
+                break;
+            }
+            case Leap::Gesture::TYPE_SWIPE:
+            {
+                Leap::SwipeGesture swipe = gesture;
+
+                // Comment to post begin and update swipes
+                if (swipe.state() != Leap::Gesture::STATE_STOP)
+                {
+                    break;
+                }
+
+                InputEvent event;
+            
+                event.deviceInst = 0;
+                event.iValue = g;
+                event.fValues[0] = (F32)swipe.state();
+                event.fValues[1] = swipe.direction().x;
+                event.fValues[2] = swipe.direction().y;
+                event.fValues[3] = swipe.direction().z;
+                event.fValues[4] = swipe.speed();
+                event.deviceType = LeapMotionDeviceType;
+                event.objType = SI_SWIPE_GESTURE;
+                event.objInst = 0;
+                event.action = SI_GESTURE;
+                event.modifier = 0;
+            
+                Game->postEvent(event);
+                break;
+            }
+            case Leap::Gesture::TYPE_KEY_TAP:
+            {
+                Leap::KeyTapGesture tap = gesture;
+
+                InputEvent event;
+            
+                event.deviceInst = 0;
+                event.iValue = g;
+                event.fValues[0] = tap.position().x;
+                event.fValues[1] = tap.position().y;
+                event.fValues[2] = tap.position().z;
+                event.fValues[3] = tap.direction().x;
+                event.fValues[4] = tap.direction().y;
+                event.fValues[5] = tap.direction().z;
+                event.deviceType = LeapMotionDeviceType;
+                event.objType = SI_KEYTAP_GESTURE;
+                event.objInst = 0;
+                event.action = SI_GESTURE;
+                event.modifier = 0;
+            
+                Game->postEvent(event);
+                break;
+            }
+            case Leap::Gesture::TYPE_SCREEN_TAP:
+            {
+                Leap::ScreenTapGesture screentap = gesture;
+
+                InputEvent event;
+            
+                event.deviceInst = 0;
+                event.iValue = g;
+                event.fValues[0] = screentap.position().x;
+                event.fValues[1] = screentap.position().y;
+                event.fValues[2] = screentap.position().z;
+                event.fValues[3] = screentap.direction().x;
+                event.fValues[4] = screentap.direction().y;
+                event.fValues[5] = screentap.direction().z;
+                event.deviceType = LeapMotionDeviceType;
+                event.objType = SI_SCREENTAP_GESTURE;
+                event.objInst = 0;
+                event.action = SI_GESTURE;
+                event.modifier = 0;
+            
+                Game->postEvent(event);
+                break;
+            }
+            default:
+                Con::warnf("LeapMotionManager::process() - Unknown gesture detected");
+                break;
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::process(const Leap::Controller& controller)
+{
+    // Is the manager enabled?
+    if (!mEnabled)
+        return;
+
+    // Was the leap device activated
+    if (!getActive())
+        return;
+
+    // Get the current frame
+    const Leap::Frame frame = controller.frame();
+
+    if (!frame.isValid())
+        return;
+
+    mLastFrame = frame;
+
+    // Get gestures
+    const Leap::GestureList gestures = frame.gestures();
+
+    if (!gestures.isEmpty())
+        processGestures(gestures);
+
+    if (getMouseControlToggle())
+    {
+        generateMouseEvent(controller);
+        return;
+    }
+
+    // Is a hand present?
+    if ( !frame.hands().isEmpty() ) 
+    {
+        for (int h = 0; h < frame.hands().count(); ++h)
+        {
+            const Leap::Hand hand = frame.hands()[h];
+
+            processHand(hand, h);
+            
+        }
+    }
+    
+    if (frame.pointables().count())
+    {
+        const Leap::PointableList pointables = frame.pointables();
+        
+        if (pointables.count())
+            processHandPointables(pointables);
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::generateMouseEvent(Leap::Controller const & controller)
+{
+    
+    const Leap::ScreenList screens = controller.locatedScreens();
+
+    // make sure we have a detected screen
+    if (screens.isEmpty())
+        return;
+
+    const Leap::Screen screen = screens[0];
+
+    // find the first finger or tool
+    const Leap::Frame frame = controller.frame();
+    const Leap::HandList hands = frame.hands();
+
+    if (hands.isEmpty())
+        return;
+
+    const Leap::PointableList pointables = hands[0].pointables();
+
+    if (pointables.isEmpty())
+        return;
+
+    const Leap::Pointable firstPointable = pointables[0];
+
+    // get x, y coordinates on the first screen
+    const Leap::Vector intersection = screen.intersect( firstPointable, true, 1.0f );
+
+    // if the user is not pointing at the screen all components of
+    // the returned vector will be Not A Number (NaN)
+    // isValid() returns true only if all components are finite
+    if (!intersection.isValid())
+        return;
+
+    F32 x = screen.widthPixels() * intersection.x;
+
+    // flip y coordinate to standard top-left origin
+    F32 y = screen.heightPixels() * (1.0f - intersection.y);
+
+    // Move the cursor
+    Point2I location((S32)x, (S32)y);
+    Canvas->setCursorPos(location);
+
+    // Build and postthe mouse event
+    MouseMoveEvent TorqueEvent;
+    TorqueEvent.xPos = (S32) location.x;
+    TorqueEvent.yPos = (S32) location.y;
+    Game->postEvent(TorqueEvent);
+}
+
+//-----------------------------------------------------------------------------
+
+Vector2 LeapMotionManager::getPointFromProjection(Point3F position)
+{
+    // Get the screen and projection
+    const Leap::Vector pointablePosition(position.x, position.y, position.z);
+    const Leap::Screen screen = mController->locatedScreens()[0];
+    const Leap::Vector projectedPosition = screen.project(pointablePosition, true, 1.0f);    
+
+    // if the user is not pointing at the screen all components of
+    // the returned vector will be Not A Number (NaN)
+    // isValid() returns true only if all components are finite
+    if (!projectedPosition.isValid())
+        return Vector2("");
+        
+    // Get the screen coordinates
+    F32 x = screen.widthPixels() * projectedPosition.x;
+        
+    // flip y coordinate to standard top-left origin
+    F32 y = screen.heightPixels() * (1.0f - projectedPosition.y);
+    
+    // Build the screenPosition and return it
+    Vector2 screenPosition;
+    screenPosition.x = x;
+    screenPosition.y = y;
+
+    return screenPosition;
+}
+
+//-----------------------------------------------------------------------------
+
+Vector2 LeapMotionManager::getPointFromIntersection(S32 pointableID)
+{
+    // Get the finger via ID and check for validity
+    Leap::Pointable lastPointable = mLastFrame.pointable(pointableID);
+
+    if (!lastPointable.isValid())
+        return Vector2("");
+
+    // Get the screen and intersection
+    const Leap::Screen screen = mController->locatedScreens()[0];
+    const Leap::Vector intersection = screen.intersect( lastPointable, true, 1.0f );
+    
+    // if the user is not pointing at the screen all components of
+    // the returned vector will be Not A Number (NaN)
+    // isValid() returns true only if all components are finite
+    if (!intersection.isValid())
+        return Vector2("");
+        
+    // Get the screen coordinates
+    F32 x = screen.widthPixels() * intersection.x;
+        
+    // flip y coordinate to standard top-left origin
+    F32 y = screen.heightPixels() * (1.0f - intersection.y);
+    
+    // Build the screenPosition and return it
+    Vector2 screenPosition;
+    screenPosition.x = x;
+    screenPosition.y = y;
+
+    return screenPosition;
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::MotionListener::onInit(const Leap::Controller& controller)
+{
+    //Con::printf("MotionListener::onInit()");
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::MotionListener::onFrame(const Leap::Controller& controller)
+{
+    gLeapMotionManager->process(controller);
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::MotionListener::onConnect(const Leap::Controller& controller)
+{
+    gLeapMotionManager->setActive(true);
+    controller.enableGesture(Leap::Gesture::TYPE_CIRCLE);
+    controller.enableGesture(Leap::Gesture::TYPE_KEY_TAP);
+    controller.enableGesture(Leap::Gesture::TYPE_SCREEN_TAP);
+    controller.enableGesture(Leap::Gesture::TYPE_SWIPE);
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::MotionListener::onDisconnect (const Leap::Controller& controller)
+{
+    gLeapMotionManager->setActive(false);
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::MotionListener::onFocusGained(const Leap::Controller& controller)
+{
+    gLeapMotionManager->setActive(true);
+}
+
+//-----------------------------------------------------------------------------
+
+void LeapMotionManager::MotionListener::onFocusLost(const Leap::Controller& controller)
+{
+    gLeapMotionManager->setActive(false);
+}

+ 162 - 0
engine/source/input/leapMotion/leapMotionManager.h

@@ -0,0 +1,162 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+#ifndef _LEAPMOTIONMANAGER_H_
+#define _LEAPMOTIONMANAGER_H_
+
+#ifndef _UTILITY_H_
+#include "2d/core/Utility.h"
+#endif
+
+#ifndef _LEAPMOTIONCONSTANTS_H_
+#include "input/leapMotion/leapMotionConstants.h"
+#endif
+
+#ifndef __Leap_h__
+#include "Leap.h"
+#endif
+
+
+class LeapMotionManager
+{
+protected:
+    
+    bool mEnabled;
+    F32 mMinCircleProgress;
+
+    struct FingerEvent
+    {
+        S32 id;
+        F32 x;
+        F32 y;
+        F32 z;
+
+        FingerEvent( S32 ID, F32 X, F32 Y, F32 Z)
+        {
+            id = ID;
+            x = X;
+            y = Y;
+            z = Z;
+        }
+    };
+
+    class MotionListener : public Leap::Listener
+    {
+    public:
+        MotionListener() {}
+        virtual ~MotionListener() {}
+
+        virtual void onConnect (const Leap::Controller& controller);
+        virtual void onDisconnect (const Leap::Controller& controller);
+        virtual void onInit(const Leap::Controller& controller);
+        virtual void onFrame(const Leap::Controller& controller);
+        virtual void onFocusGained(const Leap::Controller& controller);
+        virtual void onFocusLost(const Leap::Controller& controller);
+   };
+
+    /// The connection to the Leap Motion
+    Leap::Controller* mController;
+
+    /// Our Leap Motion listener class
+    MotionListener* mListener;
+
+    /// Used with the LM listener object
+    void* mActiveMutex;
+
+    /// Is the Leap Motion active
+    bool mActive;
+
+    /// Is the Manager acting like a mouse
+    bool mMouseControl;
+
+    /// Last stored frame
+    Leap::Frame mLastFrame;
+
+public:
+    static bool smEnableDevice;
+
+    // Indicates that events for each hand and pointable will be created
+    static bool smGenerateIndividualEvents;
+
+    // Indicates that we track hand IDs and will ensure that the same hand
+    // will remain at the same index between frames.
+    static bool smKeepHandIndexPersistent;
+
+    // Indicates that we track pointable IDs and will ensure that the same
+    // pointable will remain at the same index between frames.
+    static bool smKeepPointableIndexPersistent;
+
+    // Broadcast single hand rotation as axis
+    static bool smGenerateSingleHandRotationAsAxisEvents;
+
+    // The maximum hand angle when used as an axis event
+    // as measured from a vector pointing straight up (in degrees)
+    static F32 smMaximumHandAxisAngle;
+
+    // Indicates that a whole frame event should be generated and frames
+    // should be buffered.
+    static bool smGenerateWholeFrameEvents;
+
+    // Frame action codes
+    static U32 LM_FRAMEVALIDDATA;    // SI_BUTTON
+
+    // Hand action codes
+    static U32 LM_HAND[LeapMotionConstants::MaxHands];    // SI_POS
+    //static U32 LM_HANDROT[LeapMotionConstants::MaxHands]; // SI_ROT
+
+    static U32 LM_HANDAXISX;   // SI_AXIS
+    static U32 LM_HANDAXISY;
+
+    // Pointables action codes
+    static U32 LM_HANDPOINTABLE[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand];    // SI_POS
+    static U32 LM_HANDPOINTABLEROT[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand]; // SI_ROT
+
+    // Whole frame
+    static U32 LM_FRAME;    // SI_INT
+
+public:
+    LeapMotionManager();
+    ~LeapMotionManager();
+
+    static void staticInit();
+
+    void enable(bool enabledState);
+    void disable();
+    bool getEnabled() { return mEnabled; }
+    bool getActive();
+    void setActive(bool enabledState);
+    void toggleMouseControl(bool enabledState);
+    bool getMouseControlToggle();
+    bool setMinCircleProgress(const F32 value);
+    F32 getMinCircleProgress() { return mMinCircleProgress; }
+    bool configureLeapGesture(const char* configString, const F32 value);
+    void process(const Leap::Controller& controller);
+    void processHand(const Leap::Hand& hand, S32 id);
+    void processHandPointables(const Leap::PointableList& pointables);
+    void processGestures(const Leap::GestureList& gestures);
+    void generateMouseEvent(const Leap::Controller& controller);
+    Vector2 getPointFromProjection(Point3F position);
+    Vector2 getPointFromIntersection(S32 pointableID);
+};
+
+static LeapMotionManager* gLeapMotionManager;
+
+#endif

+ 109 - 0
engine/source/input/leapMotion/leapMotionUtil.cpp

@@ -0,0 +1,109 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "input/leapMotion/leapMotionUtil.h"
+
+namespace LeapMotionUtil
+{
+
+void convertPosition(const Leap::Vector& inPosition, F32& x, F32& y, F32& z)
+{
+    // Convert to Torque coordinates.  The conversion is:
+    //
+    // Motion       Torque
+    // x y z   -->  x -z y
+    x = inPosition.x;    // x = x
+    y = -inPosition.z;   // y = -z
+    z = inPosition.y;    // z = y;
+}
+
+void convertPosition(const Leap::Vector& inPosition, Point3F& outPosition)
+{
+    // Convert to Torque coordinates.  The conversion is:
+    //
+    // Motion       Torque
+    // x y z   -->  x -z y
+    outPosition.x = inPosition.x;    // x = x
+    outPosition.y = -inPosition.z;   // y = -z
+    outPosition.z = inPosition.y;    // z = y;
+}
+
+void convertHandRotation(const Leap::Hand& hand, MatrixF& outRotation)
+{
+    // We need to convert from Motion coordinates to
+    // Torque coordinates.  The conversion is:
+    //
+    // Motion                       Torque
+    // a b c         a  b  c        a -c  b
+    // d e f   -->  -g -h -i  -->  -g  i -h
+    // g h i         d  e  f        d -f  e
+    const Leap::Vector& handToFingers = hand.direction();
+    Leap::Vector handFront = -handToFingers;
+    const Leap::Vector& handDown = hand.palmNormal();
+    Leap::Vector handUp = -handDown;
+    Leap::Vector handRight = handUp.cross(handFront);
+
+    outRotation.setColumn(0, Point4F(  handRight.x, -handRight.z,  handRight.y,  0.0f));
+    outRotation.setColumn(1, Point4F( -handFront.x,  handFront.z, -handFront.y,  0.0f));
+    outRotation.setColumn(2, Point4F(  handUp.x,    -handUp.z,     handUp.y,     0.0f));
+    outRotation.setPosition(Point3F::Zero);
+}
+
+void calculateHandAxisRotation(const MatrixF& handRotation, const F32& maxHandAxisRadius, Point2F& outRotation)
+{
+    const VectorF& controllerUp = handRotation.getUpVector();
+    outRotation.x = controllerUp.x;
+    outRotation.y = controllerUp.y;
+
+    // Limit the axis angle to that given to us
+    if (outRotation.len() > maxHandAxisRadius)
+    {
+        outRotation.normalize(maxHandAxisRadius);
+    }
+
+    // Renormalize to the range of 0..1
+    if (maxHandAxisRadius != 0.0f)
+    {
+        outRotation /= maxHandAxisRadius;
+    }
+}
+
+void convertPointableRotation(const Leap::Pointable& pointable, MatrixF& outRotation)
+{
+    // We need to convert from Motion coordinates to
+    // Torque coordinates.  The conversion is:
+    //
+    // Motion                       Torque
+    // a b c         a  b  c        a -c  b
+    // d e f   -->  -g -h -i  -->  -g  i -h
+    // g h i         d  e  f        d -f  e
+    Leap::Vector pointableFront = -pointable.direction();
+    Leap::Vector pointableRight = Leap::Vector::up().cross(pointableFront);
+    Leap::Vector pointableUp = pointableFront.cross(pointableRight);
+
+    outRotation.setColumn(0, Point4F(  pointableRight.x, -pointableRight.z,  pointableRight.y,  0.0f));
+    outRotation.setColumn(1, Point4F( -pointableFront.x,  pointableFront.z, -pointableFront.y,  0.0f));
+    outRotation.setColumn(2, Point4F(  pointableUp.x,    -pointableUp.z,     pointableUp.y,     0.0f));
+    outRotation.setPosition(Point3F::Zero);
+}
+
+}

+ 48 - 0
engine/source/input/leapMotion/leapMotionUtil.h

@@ -0,0 +1,48 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _LEAPMOTIONUTIL_H_
+#define _LEAPMOTIONUTIL_H_
+
+#include "math/mPoint.h"
+#include "math/mMatrix.h"
+#include "Leap.h"
+
+namespace LeapMotionUtil
+{
+    /// Convert from a Leap Motion position to a Torque 3D position
+    void convertPosition(const Leap::Vector& inPosition, F32& x, F32& y, F32& z);
+
+    /// Convert from a Leap Motion position to a Torque 3D Point3F
+    void convertPosition(const Leap::Vector& inPosition, Point3F& outPosition);
+
+    /// Convert a Leap Motion hand's rotation to a Torque 3D matrix
+    void convertHandRotation(const Leap::Hand& hand, MatrixF& outRotation);
+
+    /// Calcualte a hand's rotation as if it were a thumb stick axis
+    void calculateHandAxisRotation(const MatrixF& handRotation, const F32& maxHandAxisRadius, Point2F& outRotation);
+
+    /// Convert a Leap Motion pointable's rotation to a Torque 3D matrix
+    void convertPointableRotation(const Leap::Pointable& pointable, MatrixF& outRotation);
+}
+
+#endif

+ 13 - 0
engine/source/math/mMatrix.h

@@ -149,6 +149,12 @@ public:
    /// This is the 4th column of the matrix.
    void      setPosition( const Point3F &pos ){ setColumn( 3, pos ); }
 
+   /// Get the z axis of the matrix.
+   ///
+   /// This is the 3rd column of the matrix and is
+   /// normally considered the up vector.   
+   VectorF getUpVector() const;
+
    MatrixF&  mul(const MatrixF &a);                    ///< M * a -> M
    MatrixF&  mul(const MatrixF &a, const MatrixF &b);  ///< a * b -> M
 
@@ -452,4 +458,11 @@ inline Point3F MatrixF::getPosition() const
    return pos;
 }
 
+inline VectorF MatrixF::getUpVector() const
+{
+   VectorF vec;
+   getColumn( 2, &vec );
+   return vec;
+}
+
 #endif //_MMATRIX_H_

+ 55 - 0
engine/source/math/mPoint.cpp

@@ -0,0 +1,55 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "platform/platform.h"
+#include "math/mPoint.h"
+
+
+const Point2I Point2I::One(1, 1);
+const Point2I Point2I::Zero(0, 0);
+const Point2I Point2I::Min(S32_MIN, S32_MIN);
+const Point2I Point2I::Max(S32_MAX, S32_MAX);
+
+const Point2F Point2F::One(1.0f, 1.0f);
+const Point2F Point2F::Zero(0.0f, 0.0f);
+const Point2F Point2F::Min(F32_MIN, F32_MIN);
+const Point2F Point2F::Max(F32_MAX, F32_MAX);
+
+const Point2D Point2D::One(1.0, 1.0);
+const Point2D Point2D::Zero(0.0, 0.0);
+
+const Point3I Point3I::One(1, 1, 1);
+const Point3I Point3I::Zero(0, 0, 0);
+
+const Point3F Point3F::One(1.0f, 1.0f, 1.0f);
+const Point3F Point3F::Zero(0.0f, 0.0f, 0.0f);
+const Point3F Point3F::Min(F32_MIN, F32_MIN, F32_MIN);
+const Point3F Point3F::Max(F32_MAX, F32_MAX, F32_MAX);
+const Point3F Point3F::UnitX(1.0f, 0.0f, 0.0f);
+const Point3F Point3F::UnitY(0.0f, 1.0f, 0.0f);
+const Point3F Point3F::UnitZ(0.0f, 0.0f, 1.0f);
+
+const Point3D Point3D::One(1.0, 1.0, 1.0);
+const Point3D Point3D::Zero(0.0, 0.0, 0.0);
+
+const Point4F Point4F::One(1.0f, 1.0f, 1.0f, 1.0f);
+const Point4F Point4F::Zero(0.0f, 0.0f, 0.0f, 0.0f);

+ 45 - 0
engine/source/math/mPoint.h

@@ -82,6 +82,13 @@ class Point2I
 
    // Unary operators
    Point2I operator-() const;
+
+   //-------------------------------------- Public static constants
+  public:
+	const static Point2I One;
+	const static Point2I Zero;
+	const static Point2I Min;
+	const static Point2I Max;
 };
 
 //------------------------------------------------------------------------------
@@ -135,6 +142,11 @@ class Point3I
 
    // Unary operators
    Point3I operator-() const;
+
+   //-------------------------------------- Public static constants
+public:
+   const static Point3I One;
+   const static Point3I Zero;
 };
 
 
@@ -207,6 +219,14 @@ class Point2F
 
    // Unary operators
    Point2F operator-() const;
+
+   //-------------------------------------- Public static constants
+  public:
+	const static Point2F One;
+	const static Point2F Zero;
+	const static Point2F Min;
+	const static Point2F Max;
+
 };
 
 
@@ -277,6 +297,11 @@ class Point2D
 
    // Unary operators
    Point2D operator-() const;
+
+//-------------------------------------- Public static constants
+  public:
+    const static Point2D One;
+    const static Point2D Zero;
 };
 
 
@@ -349,6 +374,16 @@ class Point3F
 
    // Unary operators
    Point3F operator-() const;
+
+   //-------------------------------------- Public static constants
+public:
+   const static Point3F One;
+   const static Point3F Zero;
+   const static Point3F Max;
+   const static Point3F Min;
+   const static Point3F UnitX;
+   const static Point3F UnitY;
+   const static Point3F UnitZ;
 };
 
 
@@ -416,6 +451,11 @@ class Point3D
 
    // Unary operators
    Point3D operator-() const;
+
+   //-------------------------------------- Public static constants
+public:
+   const static Point3D One;
+   const static Point3D Zero;
 };
 
 
@@ -453,6 +493,11 @@ class Point4F
 
    operator F32*() { return (&x); }
    operator F32*() const { return (F32*)(&x); }
+
+   	//-------------------------------------- Public static constants
+  public:
+	const static Point4F One;
+	const static Point4F Zero;
 };
 
 

+ 55 - 27
engine/source/platform/event.h

@@ -177,11 +177,8 @@ struct ScreenTouchEvent : public Event
 struct InputEvent : public Event
 {
    U32   deviceInst;  ///< Device instance: joystick0, joystick1, etc
-   F32   fValue;      ///< Value ranges from -1.0 to 1.0
-   F32   fValue2;
-   F32   fValue3;
-   F32   fValue4;
-   S32   iValue;
+   S32 iValue;        ///< Handy for tracking IDs of things like fingers, hands, etc
+   float fValues[7];  ///< Stores the evemt data. Sometimes only one with a range of -1.0 - 1.0 is needed, other times it might be multiple vectors
    U16   deviceType;  ///< One of mouse, keyboard, joystick, unknown
    U16   objType;     ///< One of SI_XAXIS, SI_BUTTON, SI_KEY ...
    U16   ascii;       ///< ASCII character code if this is a keyboard event.
@@ -190,13 +187,30 @@ struct InputEvent : public Event
    U8    modifier;    ///< Modifier to action: SI_LSHIFT, SI_LCTRL, etc.
 
    // iOS specific
-   char touchesX[256];    ///< Collection of x-coordinates for touches
-   char touchesY[256];    ///< Collection of y-coordinates for touches
-   char touchIDs[256];    ///< Collection of touch IDs
+   char fingersX[256];    ///< Collection of x-coordinates for fingers
+   char fingersY[256];    ///< Collection of y-coordinates for fingers
+   char fingersZ[256];    ///< Collection of Z-coordinates for fingers
+
+   char fingerIDs[256];    ///< Collection of touch IDs
     
-   InputEvent() { type = InputEventType; size = sizeof(InputEvent); dMemset(touchesX, 0, sizeof(touchesX)); 
-                                                                    dMemset(touchesY, 0, sizeof(touchesY));
-                                                                    dMemset(touchIDs, 0, sizeof(touchIDs));}
+    InputEvent()
+    { 
+        type = InputEventType; 
+        size = sizeof(InputEvent); 
+        deviceInst = 0;
+        iValue     = -1;
+        objType    = 0;
+        ascii      = 0;
+        objInst    = 0;
+        action     = 0;
+        modifier   = 0;
+        dMemset(fValues, 0, sizeof(fValues));
+        dMemset(fingersX, 0, sizeof(fingersX));
+        dMemset(fingersY, 0, sizeof(fingersY));
+        dMemset(fingersZ, 0, sizeof(fingersZ));
+        dMemset(fingerIDs, 0, sizeof(fingerIDs));
+    }
+
 };
 
 /// @defgroup input_constants Input system constants
@@ -447,9 +461,24 @@ enum TouchCodes
    SI_TOUCHDOWN   = 0x30C,
    SI_TOUCHUP     = 0x30D,
    SI_TOUCHMOVE   = 0x30E,
-   SI_PINCH       = 0x30F,
-   SI_SCALE       = 0x401,
-   SI_TAP         = 0x402
+};
+
+enum GestureCodes
+{
+    SI_CIRCLE_GESTURE    = 0x403,
+    SI_SWIPE_GESTURE     = 0x404,
+    SI_KEYTAP_GESTURE    = 0x405,
+    SI_SCREENTAP_GESTURE = 0x406,
+    SI_PINCH_GESTURE     = 0x407,
+    SI_SCALE_GESTURE     = 0x408
+};
+
+enum LeapMotionCodes
+{
+    LM_HANDAXIS          = 0x409,
+    LM_HANDROT           = 0x40A,
+    LM_HANDPOS           = 0x40B,
+    LM_FINGERPOS         = 0x40C,
 };
 
 /// Input device types
@@ -463,8 +492,8 @@ enum InputDeviceTypes
    XInputDeviceType,
    ScreenTouchDeviceType,
    AccelerometerDeviceType,
-   GyroscopeDeviceType
-
+   GyroscopeDeviceType,
+   LeapMotionDeviceType
 };
 
 /// Device Event Action Types
@@ -474,17 +503,16 @@ enum InputDeviceTypes
 #define SI_REPEAT    0x04
 #define SI_VALUE	 0x05
 
-//Device Event Types
-#define SI_UNKNOWN   0x01
-#define SI_BUTTON    0x02
-#define SI_POV       0x03
-#define SI_KEY       0x0A
-#define SI_TEXT      0x0B
-#define SI_TOUCH     0x0C
-#define SI_GESTURE   0x0D
-#define SI_MOTION    0x0F
-
-
+///Device Event Types
+#define SI_UNKNOWN           0x01
+#define SI_BUTTON            0x02
+#define SI_POV               0x03
+#define SI_KEY               0x0A
+#define SI_TEXT              0x0B
+#define SI_TOUCH             0x0C
+#define SI_GESTURE           0x0D
+#define SI_MOTION            0x0F
+#define SI_LEAP              0x11
 
 /// Event SubTypes
 #define SI_ANY       0xff

+ 8 - 8
engine/source/platformWin32/winDInputDevice.cc

@@ -917,7 +917,7 @@ bool DInputDevice::buildEvent( DWORD offset, S32 newData, S32 oldData )
          newEvent.action = SI_MOVE;
          if ( newEvent.deviceType == MouseDeviceType )
          {
-            newEvent.fValue = float( newData );
+            newEvent.fValues[0] = float( newData );
 
          }
          else  // Joystick or other device:
@@ -926,11 +926,11 @@ bool DInputDevice::buildEvent( DWORD offset, S32 newData, S32 oldData )
             if ( objInfo.mMin != DIPROPRANGE_NOMIN && objInfo.mMax != DIPROPRANGE_NOMAX )
             {
                float range = float( objInfo.mMax - objInfo.mMin );
-               //newEvent.fValue = float( newData - objInfo.mMin ) / range;
-               newEvent.fValue = float( ( 2 * newData ) - objInfo.mMax - objInfo.mMin ) / range;
+               //newEvent.fValues[0] = float( newData - objInfo.mMin ) / range;
+               newEvent.fValues[0] = float( ( 2 * newData ) - objInfo.mMax - objInfo.mMin ) / range;
             }
             else
-               newEvent.fValue = (F32)newData;
+               newEvent.fValues[0] = (F32)newData;
          }
 
          Game->postEvent( newEvent );
@@ -938,14 +938,14 @@ bool DInputDevice::buildEvent( DWORD offset, S32 newData, S32 oldData )
 
       case SI_BUTTON:
          newEvent.action   = ( newData & 0x80 ) ? SI_MAKE : SI_BREAK;
-         newEvent.fValue   = ( newEvent.action == SI_MAKE ) ? 1.0f : 0.0f;
+         newEvent.fValues[0]   = ( newEvent.action == SI_MAKE ) ? 1.0f : 0.0f;
 
          Game->postEvent( newEvent );
          break;
 
       case SI_KEY:
          newEvent.action   = ( newData & 0x80 ) ? SI_MAKE : SI_BREAK;
-         newEvent.fValue   = ( newEvent.action == SI_MAKE ) ? 1.0f : 0.0f;
+         newEvent.fValues[0]   = ( newEvent.action == SI_MAKE ) ? 1.0f : 0.0f;
          processKeyEvent( newEvent );
 
          Game->postEvent( newEvent );
@@ -975,7 +975,7 @@ bool DInputDevice::buildEvent( DWORD offset, S32 newData, S32 oldData )
             if ( clearkeys )
             {
                newEvent.action = SI_BREAK;
-               newEvent.fValue = 0.0f;
+               newEvent.fValues[0] = 0.0f;
                // post events for all buttons that need to be cleared.
                if( clearkeys & POV_up)
                {
@@ -1006,7 +1006,7 @@ bool DInputDevice::buildEvent( DWORD offset, S32 newData, S32 oldData )
             if ( setkeys )
             {
                newEvent.action = SI_MAKE;
-               newEvent.fValue = 1.0f;
+               newEvent.fValues[0] = 1.0f;
                // post events for all buttons that need to be set.
                if( setkeys & POV_up)
                {

+ 1 - 1
engine/source/platformWin32/winDirectInput.cc

@@ -652,7 +652,7 @@ InputEvent newEvent;
    newEvent.objType = objType;
    newEvent.objInst = objInst;
    newEvent.action = action;
-   newEvent.fValue = fValue;
+   newEvent.fValues[0] = fValue;
    //we need to find the gameinterface object from here
 
    Game->postEvent(newEvent);

+ 5 - 5
engine/source/platformWin32/winWindow.cc

@@ -480,7 +480,7 @@ static void processKeyMessage(UINT message, WPARAM wParam, LPARAM lParam)
    event.action     = make ? (repeat ? SI_REPEAT : SI_MAKE ) : SI_BREAK;
    event.modifier   = modKey;
    event.ascii      = asciiCode;
-   event.fValue     = make ? 1.0f : 0.0f;
+   event.fValues[0]     = make ? 1.0f : 0.0f;
 
    // Store the current modifier keys
    Input::setModifierKeys(modifierKeys);
@@ -547,7 +547,7 @@ static void CheckCursorPos()
          event.action = SI_MOVE;
          event.modifier = modifierKeys;
          event.ascii = 0;
-         event.fValue = (F32)(mousePos.x - centerX);
+         event.fValues[0] = (F32)(mousePos.x - centerX);
          Game->postEvent(event);
       }
 
@@ -562,7 +562,7 @@ static void CheckCursorPos()
          event.action = SI_MOVE;
          event.modifier = modifierKeys;
          event.ascii = 0;
-         event.fValue = (F32)(mousePos.y - centerY);
+         event.fValues[0] = (F32)(mousePos.y - centerY);
          Game->postEvent(event);
       }
 
@@ -596,7 +596,7 @@ static void mouseButtonEvent(S32 action, S32 objInst)
    event.action = action;
    event.modifier = modifierKeys;
    event.ascii = 0;
-   event.fValue = action == SI_MAKE ? 1.0f : 0.0f;
+   event.fValues[0] = action == SI_MAKE ? 1.0f : 0.0f;
 
    Game->postEvent(event);
 }
@@ -619,7 +619,7 @@ static void mouseWheelEvent( S32 delta )
       event.action = SI_MOVE;
       event.modifier = modifierKeys;
       event.ascii = 0;
-      event.fValue = (F32)delta;
+      event.fValues[0] = (F32)delta;
 
       Game->postEvent( event );
    }

+ 7 - 0
modules/LeapToy/1/assets/animations/Digital_ExplosionAnimation.asset.taml

@@ -0,0 +1,7 @@
+<AnimationAsset
+    AssetName="Digital_ExplosionAnimation"
+    Image="@asset=LeapToy:Digital_ExplosionSprite"
+    animationFrames="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
+    animationTime="1"
+    animationCycle="0"
+     />

+ 5 - 0
modules/LeapToy/1/assets/animations/Projectile_Digital_StrikeAnimation.asset.taml

@@ -0,0 +1,5 @@
+<AnimationAsset
+    AssetName="Projectile_Digital_StrikeAnimation"
+    Image="@asset=LeapToy:Projectile_Digital_StrikeSprite"
+    AnimationFrames="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
+    AnimationTime="1" />

+ 6 - 0
modules/LeapToy/1/assets/animations/blockAnim.asset.taml

@@ -0,0 +1,6 @@
+<AnimationAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+                AssetName="blockAnim"
+                Image="@asset=LeapToy:objectsBlocks"
+                AnimationCycle="1"
+                AnimationTime="2"
+                AnimationFrames="0 1 2 3 4 5 6 7"/>

+ 6 - 0
modules/LeapToy/1/assets/animations/brickAnim.asset.taml

@@ -0,0 +1,6 @@
+<AnimationAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+                AssetName="brickAnim"
+                Image="@asset=LeapToy:objectsBricks"
+                AnimationCycle="1"
+                AnimationTime="2"
+                AnimationFrames="0 1 2 3 4 5 6 7 8 9 10 11"/>

+ 8 - 0
modules/LeapToy/1/assets/images/Digital_Explosion.asset.taml

@@ -0,0 +1,8 @@
+<ImageAsset
+    AssetName="Digital_ExplosionSprite"
+    imageFile="Digital_Explosion.png"
+    cellCountX="4"
+    cellCountY="4"
+    cellWidth="128"
+    cellHeight="128"
+	 />

BIN
modules/LeapToy/1/assets/images/Digital_Explosion.png


+ 8 - 0
modules/LeapToy/1/assets/images/Projectile_Digital_Strike.asset.taml

@@ -0,0 +1,8 @@
+<ImageAsset
+    AssetName="Projectile_Digital_StrikeSprite"
+    imageFile="Projectile_Digital_Strike.png"
+    cellCountX="4"
+    cellCountY="4"
+    cellWidth="64"
+    cellHeight="96"
+	 />

BIN
modules/LeapToy/1/assets/images/Projectile_Digital_Strike.png


+ 3 - 0
modules/LeapToy/1/assets/images/barrierWall.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+            AssetName="barrierWall"
+            ImageFile="barrierWall.png"/>

BIN
modules/LeapToy/1/assets/images/barrierWall.png


+ 3 - 0
modules/LeapToy/1/assets/images/blockGlow.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+            AssetName="blockGlow"
+            ImageFile="blockGlow.png"/>

BIN
modules/LeapToy/1/assets/images/blockGlow.png


+ 3 - 0
modules/LeapToy/1/assets/images/circleThree.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+            AssetName="circleThree"
+            ImageFile="circleThree.png"/>

BIN
modules/LeapToy/1/assets/images/circleThree.png


+ 3 - 0
modules/LeapToy/1/assets/images/complexCircle.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+            AssetName="complexCircle"
+            ImageFile="complexCircle.png"/>

BIN
modules/LeapToy/1/assets/images/complexCircle.png


+ 3 - 0
modules/LeapToy/1/assets/images/menuBackground.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+            AssetName="menuBackground"
+            ImageFile="menuBackground.jpg"/>

BIN
modules/LeapToy/1/assets/images/menuBackground.jpg


+ 9 - 0
modules/LeapToy/1/assets/images/objectsBlocks.asset.taml

@@ -0,0 +1,9 @@
+<ImageAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+            AssetName="objectsBlocks"
+            ImageFile="objectsBlocks.png"
+            CellCountX="2"
+            CellCountY="4"
+            CellWidth="56"
+            CellHeight="55"
+            CellOffsetY="1"
+            CellOffsetX="1"/>

BIN
modules/LeapToy/1/assets/images/objectsBlocks.png


+ 7 - 0
modules/LeapToy/1/assets/images/objectsBricks.asset.taml

@@ -0,0 +1,7 @@
+<ImageAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+            AssetName="objectsBricks"
+            ImageFile="objectsBricks.png"
+            CellCountX="2"
+            CellCountY="6"
+            CellWidth="112"
+            CellHeight="64"/>

BIN
modules/LeapToy/1/assets/images/objectsBricks.png


+ 3 - 0
modules/LeapToy/1/assets/images/playerUfo.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+            AssetName="playerUfo"
+            ImageFile="playerUfo.png"/>

BIN
modules/LeapToy/1/assets/images/playerUfo.png


+ 3 - 0
modules/LeapToy/1/assets/images/simpleCircle.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+            AssetName="simpleCircle"
+            ImageFile="simpleCircle.png"/>

BIN
modules/LeapToy/1/assets/images/simpleCircle.png


+ 3 - 0
modules/LeapToy/1/assets/images/widgetBall.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+            AssetName="widgetBall"
+            ImageFile="widgetBall.png"/>

BIN
modules/LeapToy/1/assets/images/widgetBall.png


+ 3 - 0
modules/LeapToy/1/assets/images/widgetFruit.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+            AssetName="widgetFruit"
+            ImageFile="widgetFruit.png"/>

BIN
modules/LeapToy/1/assets/images/widgetFruit.png


+ 3 - 0
modules/LeapToy/1/assets/images/window.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+            AssetName="window"
+            ImageFile="window.png"/>

BIN
modules/LeapToy/1/assets/images/window.png


+ 129 - 0
modules/LeapToy/1/assets/particles/blockFadeParticle.asset.taml

@@ -0,0 +1,129 @@
+<ParticleAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+    AssetName="blockFadeParticle"
+    Lifetime="1"
+    LifeMode="KILL">
+    <ParticleAssetEmitter
+        EmitterName="fade"
+        EmitterType="POINT"
+        EmitterSize="2 1"
+        OrientationType="FIXED"
+        FixedForceAngle="0"
+        FixedAspect="0"
+        IntenseParticles="1"
+        SingleParticle="1"
+        AttachPositionToEmitter="0"
+        AttachRotationToEmitter="0"
+        LinkEmissionRotation="0"
+        OldestInFront="0"
+        Image="@asset=LeapToy:blockGlow">
+      <ParticleAssetEmitter.Fields>
+        <Lifetime>
+          <Key Time="0.000000" Value="2.000000"/>
+        </Lifetime>
+        <LifetimeVariation>
+          <Key Time="0.000000" Value="0.000000"/>
+        </LifetimeVariation>
+        <Quantity>
+          <Key Time="0.000000" Value="10.000000"/>
+        </Quantity>
+        <QuantityVariation>
+          <Key Time="0.000000" Value="0.000000"/>
+        </QuantityVariation>
+        <SizeX>
+          <Key Time="0.000000" Value="3.398734"/>
+        </SizeX>
+        <SizeXVariation>
+          <Key Time="0.000000" Value="0.000000"/>
+        </SizeXVariation>
+        <SizeXLife>
+          <Key Time="0.000000" Value="1.000000"/>
+          <Key Time="0.126863" Value="1.141772"/>
+          <Key Time="0.437451" Value="0.946836"/>
+          <Key Time="0.786863" Value="0.556963"/>
+        </SizeXLife>
+        <SizeY>
+          <Key Time="0.000000" Value="1.977848"/>
+        </SizeY>
+        <SizeYVariation>
+          <Key Time="0.000000" Value="0.000000"/>
+        </SizeYVariation>
+        <SizeYLife>
+          <Key Time="0.000000" Value="1.000000"/>
+          <Key Time="0.217451" Value="0.751899"/>
+          <Key Time="0.584118" Value="-0.417721"/>
+          <Key Time="1.000000" Value="-3.202531"/>
+        </SizeYLife>
+        <Speed>
+          <Key Time="0.000000" Value="10.000000"/>
+        </Speed>
+        <SpeedVariation>
+          <Key Time="0.000000" Value="0.000000"/>
+        </SpeedVariation>
+        <SpeedLife>
+          <Key Time="0.000000" Value="1.000000"/>
+        </SpeedLife>
+        <Spin>
+          <Key Time="0.000000" Value="0.000000"/>
+        </Spin>
+        <SpinVariation>
+          <Key Time="0.000000" Value="26.582283"/>
+        </SpinVariation>
+        <SpinLife>
+          <Key Time="0.000000" Value="1.000000"/>
+        </SpinLife>
+        <FixedForce>
+          <Key Time="0.000000" Value="0.000000"/>
+        </FixedForce>
+        <FixedForceVariation>
+          <Key Time="0.000000" Value="0.000000"/>
+        </FixedForceVariation>
+        <FixedForceLife>
+          <Key Time="0.000000" Value="1.000000"/>
+        </FixedForceLife>
+        <RandomMotion>
+          <Key Time="0.000000" Value="0.000000"/>
+        </RandomMotion>
+        <RandomMotionVariation>
+          <Key Time="0.000000" Value="0.000000"/>
+        </RandomMotionVariation>
+        <RandomMotionLife>
+          <Key Time="0.000000" Value="1.000000"/>
+        </RandomMotionLife>
+        <EmissionForce>
+          <Key Time="0.000000" Value="5.000000"/>
+        </EmissionForce>
+        <EmissionForceVariation>
+          <Key Time="0.000000" Value="0.000000"/>
+        </EmissionForceVariation>
+        <EmissionAngle>
+          <Key Time="0.000000" Value="0.000000"/>
+        </EmissionAngle>
+        <EmissionAngleVariation>
+          <Key Time="0.000000" Value="0.000000"/>
+        </EmissionAngleVariation>
+        <EmissionArc>
+          <Key Time="0.000000" Value="360.000000"/>
+        </EmissionArc>
+        <EmissionArcVariation>
+          <Key Time="0.000000" Value="0.000000"/>
+        </EmissionArcVariation>
+        <RedChannel>
+          <Key Time="0.000000" Value="1.000000"/>
+          <Key Time="0.286471" Value="0.625316"/>
+        </RedChannel>
+        <GreenChannel>
+          <Key Time="0.000000" Value="0.799367"/>
+        </GreenChannel>
+        <BlueChannel>
+          <Key Time="0.000000" Value="0.736709"/>
+          <Key Time="0.195882" Value="1.000000"/>
+        </BlueChannel>
+        <AlphaChannel>
+          <Key Time="0.000000" Value="0.200633"/>
+          <Key Time="0.040588" Value="1.000000"/>
+          <Key Time="0.178627" Value="0.409494"/>
+          <Key Time="0.471961" Value="0.000000"/>
+        </AlphaChannel>
+      </ParticleAssetEmitter.Fields>
+    </ParticleAssetEmitter>
+</ParticleAsset>

+ 69 - 0
modules/LeapToy/1/assets/particles/digitalExplosion.asset.taml

@@ -0,0 +1,69 @@
+<ParticleAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+    AssetName="digitalExplosion"
+    Lifetime="1"
+    LifeMode="KILL">
+    <ParticleAssetEmitter
+        EmitterName="debris"
+        EmitterType="BOX"
+        EmitterAngle="90"
+        EmitterSize="2 1"
+		AttachPositionToEmitter="1"
+		AttachRotationToEmitter="1"
+        FixedForceAngle="-90"
+        OldestInFront="1"
+        Image="@asset=ToyAssets:Asteroids"
+        RandomImageFrame="1">
+        <ParticleAssetEmitter.Fields>
+            <Quantity
+                Keys="0 250 0.1 150 0.11 0" />
+            <LifetimeVariation
+                Keys="0 1" />
+            <EmissionArc
+                Keys="0 90" />
+            <Speed
+                Keys="0 1.8" />
+            <SizeXVariation
+                Keys="0 2.1" />
+            <FixedForce
+                Keys="0 8" />
+            <SizeXLife
+                Keys="0 0 0.1 0.1" />
+            <RandomMotion
+                Keys="0 10" />
+            <FixedForceVariation
+                Keys="0 2" />
+            <SpinVariation
+                Keys="0 360" />
+            <SpeedVariation
+                Keys="0 0.3" />
+            <AlphaChannel
+                Keys="0 0 0.1 1 0.8 1 1 0" />
+            <EmissionAngle
+                Keys="0 90" />
+        </ParticleAssetEmitter.Fields>
+    </ParticleAssetEmitter>
+    <ParticleAssetEmitter
+        EmitterName="flames"
+        EmitterType="LINE"
+        EmitterSize="1 0"
+		AttachPositionToEmitter="1"
+		AttachRotationToEmitter="1"		
+        IntenseParticles="1"
+        OldestInFront="1"
+        Animation="@asset=LeapToy:Digital_ExplosionAnimation">
+        <ParticleAssetEmitter.Fields>
+            <Quantity
+                Keys="0 20 0.1 20 0.11 0" />
+            <Lifetime
+                Keys="0 1" />
+            <Speed
+                Keys="0 0" />
+            <SizeXVariation
+                Keys="0 2" />
+            <SizeXLife
+                Keys="0 0 0.1 3" />
+            <AlphaChannel
+                Keys="0 0 0.1 1 0.8 1 1 0" />
+        </ParticleAssetEmitter.Fields>
+    </ParticleAssetEmitter>
+</ParticleAsset>

+ 79 - 0
modules/LeapToy/1/assets/particles/digitalFire.asset.taml

@@ -0,0 +1,79 @@
+<ParticleAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../Torque2D.xsd"
+    AssetName="digitalfire">
+    <ParticleAssetEmitter
+        EmitterName="smoke"
+		EmitterType="line"
+		EmitterSize="0.5 0"
+		EmitterOffset="0 1"
+        FixedForceAngle="90"
+        OldestInFront="1"
+        Image="@asset=ToyAssets:Particles4"
+        Frame="0">
+        <ParticleAssetEmitter.Fields>
+            <Quantity
+                Keys="0 10" />
+			<EmissionAngle
+				Keys="0 90" />								
+			<EmissionArc
+				Keys="0 0" />
+            <LifetimeVariation
+                Keys="0 1" />
+            <Speed
+                Keys="0 0.3" />
+            <SpeedVariation
+                Keys="0 0.1" />
+            <FixedForce
+				Keys="0 0" />				
+            <FixedForceVariation
+                Keys="0 0" />				
+            <SizeXLife>
+				<Key Time="0" Value="0"/>
+				<Key Time="0.2" Value="1"/>
+				<Key Time="0.5" Value="1"/>
+				<Key Time="0.9" Value="1"/>
+				<Key Time="1" Value="0"/>
+			</SizeXLife>
+            <SizeXVariation
+                Keys="0 0.3" />				
+            <SpinVariation
+                Keys="0 360" />				
+            <AlphaChannel
+                Keys="0 0 0.2 0.15 1 0" />
+        </ParticleAssetEmitter.Fields>
+    </ParticleAssetEmitter>		
+    <ParticleAssetEmitter
+        EmitterName="flames"
+        EmitterType="LINE"
+        EmitterSize="1 0"
+        FixedForceAngle="90"
+        IntenseParticles="1"
+        OldestInFront="1"
+        Animation="@asset=LeapToy:Projectile_Digital_StrikeAnimation">
+        <ParticleAssetEmitter.Fields>
+            <Quantity
+                Keys="0 20" />
+            <EmissionArc
+                Keys="0 30" />
+            <Lifetime
+                Keys="0 1" />
+            <Speed
+                Keys="0 0.1" />
+            <SizeXVariation
+                Keys="0 0.2" />
+            <FixedForce
+                Keys="0 30" />
+            <SizeXLife
+                Keys="0 0 0.1 0.5" />
+            <RandomMotion
+                Keys="0 10" />
+            <FixedForceVariation
+                Keys="0 10" />
+            <SpinVariation
+                Keys="0 360" />
+            <AlphaChannel
+                Keys="0 0 0.1 1 0.8 1 1 0" />
+            <EmissionAngle
+                Keys="0 90" />
+        </ParticleAssetEmitter.Fields>
+    </ParticleAssetEmitter>
+</ParticleAsset>

+ 180 - 0
modules/LeapToy/1/main.cs

@@ -0,0 +1,180 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+function LeapToy::create( %this )
+{
+    // Execute toy scripts
+    exec("./scripts/input.cs");
+    exec("./scripts/toy.cs");
+    exec("./scripts/gestureDemo.cs");
+    exec("./scripts/breakoutDemo.cs");
+    exec("./scripts/fingerDemo.cs");
+    exec("./scripts/builderDemo.cs");
+    exec("./scripts/helpText.cs");
+    
+    exec("./scripts/DealsDamageBehavior.cs");
+    exec("./scripts/TakesDamageBehavior.cs");
+    exec("./scripts/SwapImageOnCollision.cs");
+
+    %this.handPosDeadzone = "-1.0 1.0";
+    %this.handRotDeadzone = "-1.0 1.0";
+    %this.fingerPosDeadzone = "-1.0 1.0";
+    %this.enableSwipeGesture = false;
+    %this.enableCircleGesture = false;
+    %this.enableScreenTapGesture = false;
+    %this.enableKeyTapGesture = false;
+    %this.enableHandRotation = false;
+    %this.enableFingerTracking = true;
+    %this.currentLevel = "Builder Demo";
+    
+    addFlagOption( "Enable Swipe Gesture", "setEnableSwipeGesture", LeapToy.enableSwipeGesture, false, "Turns on swipe gesture recognition" );
+    addFlagOption( "Enable Circle Gesture", "setEnableCircleGesture", LeapToy.enableCircleGesture, false, "Turns on circle gesture recognition" );
+    addFlagOption( "Enable Screen Tap Gesture", "setEnableScreenTapGesture", LeapToy.enableScreenTapGesture, false, "Turns on screen tap gesture recognition" );
+    addFlagOption( "Enable Key Tap Gesture", "setEnableKeyTapGesture", LeapToy.enableKeyTapGesture, false, "Turns on key tap gesture recognition" );
+    addFlagOption( "Enable Hand Rotation", "setEnableHandRotation", LeapToy.enableHandRotation, false, "Turns on tracking of hand rotation" );
+    addFlagOption( "Enable Finger Tracking", "setenableFingerTracking", LeapToy.enableFingerTracking, false, "Turns on tracking of finger position" );
+    
+    %options = "Gestures,Breakout,Finger Tracking,Builder Demo";
+    addSelectionOption(%options, "Level", 4, setLevel, true, "Choose which Leap Motion Demo to play");
+
+    // Set the sandbox drag mode availability.
+    Sandbox.allowManipulation( pull );
+    
+    // Configure the toy.
+    LeapToy.GroundWidth = 40;
+    LeapToy.BlockSize = 2;
+    LeapToy.BlockCount = 15;
+    LeapToy.BrickRows = 4;
+    LeapToy.BrickColumns = 9;
+    LeapToy.BrickSize = "3 1";
+    LeapToy.PaddleSpeed = 30;
+    LeapToy.maxBallSpeed = 20;
+    LeapToy.fingerCount = 0;
+    
+    // Initialize all bindings
+    %this.initializeInput();
+    
+    // Build the behaviors
+    %this.createDealsDamageBehavior();
+    %this.createTakesDamageBehavior();
+    %this.createSwapImageBehavior();
+    
+    %this.selectedObjects = new SimSet();
+    %this.add(%this.selectedObjects);
+    
+    // Reset the toy.
+    LeapToy.reset();
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::destroy( %this )
+{
+    // Turn off Leap driven cursor control, if it was activated
+    if (isLeapCursorControlled())
+        enableLeapMotionManager(false);
+    
+    %this.selectedObjects.clear();
+    %this.selectedObjects.delete();
+    // Clean up the help text
+    if (isObject(HelpTextScene))
+      HelpTextScene.delete();
+    // Clean up the ActionMaps
+    %this.destroyInput();
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::reset( %this )
+{
+    // Reset the input
+    FingerMap.pop();
+    GestureMap.pop();
+    BreakoutMap.pop();
+    BuilderMap.pop();
+    // Clean up the help text if there is one
+    %this.clearHelpTextScene();    
+      
+     // Clear the scene.
+    SandboxScene.clear();
+    
+    // Set the camera size.
+    SandboxWindow.setCameraSize( 40, 30 );
+
+    if (%this.currentLevel $= "Gestures")
+        %this.createGesturesLevel();
+    else if (%this.currentLevel $= "Breakout")
+        %this.createBreakoutLevel();
+    else if (%this.currentLevel $= "Finger Tracking")
+        %this.createFingerLevel();
+    else if (%this.currentLevel $= "Builder Demo")
+        %this.createBuilderLevel();
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::setLevel( %this, %value)
+{
+    %this.currentLevel = %value;
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::setEnableSwipeGesture( %this, %value )
+{
+    %this.enableSwipeGesture = %value;
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::setEnableCircleGesture( %this, %value )
+{
+    %this.enableCircleGesture = %value;
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::setEnableScreenTapGesture( %this, %value )
+{
+    %this.enableScreenTapGesture = %value;
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::setEnableKeyTapGesture( %this, %value )
+{
+    %this.enableKeyTapGesture = %value;
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::setEnableHandRotation( %this, %value )
+{
+    %this.enableHandRotation = %value;
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::setEnableFingerTracking( %this, %value )
+{
+    %this.enableFingerTracking = %value;
+}

+ 15 - 0
modules/LeapToy/1/module.taml

@@ -0,0 +1,15 @@
+<ModuleDefinition
+	ModuleId="LeapToy"
+	VersionId="1"
+	Description="Demonstrates Leap Motion device support."
+	Dependencies="ToyAssets=1"
+	Type="toy"
+	ToyCategoryIndex="3"
+	ScriptFile="main.cs"
+	CreateFunction="create"
+	DestroyFunction="destroy">
+        <DeclaredAssets
+            Path="assets"
+            Extension="asset.taml"
+            Recurse="true"/>		
+</ModuleDefinition>

+ 80 - 0
modules/LeapToy/1/scripts/DealsDamageBehavior.cs

@@ -0,0 +1,80 @@
+//-----------------------------------------------------------------------------
+// Torque
+// Copyright GarageGames, LLC 2013
+//-----------------------------------------------------------------------------
+
+function LeapToy::createDealsDamageBehavior( %this )
+{
+    if (!isObject(DealsDamageBehavior))
+    {
+        %this.DealsDamageBehavior = new BehaviorTemplate(DealsDamageBehavior);
+
+        %this.DealsDamageBehavior.friendlyName = "Deals Damage Advanced";
+        %this.DealsDamageBehavior.behaviorType = "Game";
+        %this.DealsDamageBehavior.description  = "Set the object to deal damage to TakesDamage objects it collides with";
+
+        %this.DealsDamageBehavior.addBehaviorField(strength, "The amount of damage the object deals", int, 10);
+        %this.DealsDamageBehavior.addBehaviorField(deleteOnHit, "Delete the object when it collides", bool, 1);
+        %this.DealsDamageBehavior.addBehaviorField(explodeEffect, "The particle effect to play on collision", asset, "", ParticleAsset);
+
+        %this.add(%this.DealsDamageBehavior);
+    }    
+}
+
+//-----------------------------------------------------------------------------
+
+function DealsDamageBehavior::initialize(%this, %strength, %deleteOnHit, %explodeEffect)
+{
+    %this.strength = %strength;
+    %this.deleteOnHit = %deleteOnHit;
+    %this.explodeEffect = %explodeEffect;
+}
+
+//-----------------------------------------------------------------------------
+
+function DealsDamageBehavior::onBehaviorAdd(%this)
+{
+    %this.owner.collisionCallback = true;
+    %this.owner.collisionActiveSend = true;
+}
+
+//-----------------------------------------------------------------------------
+
+function DealsDamageBehavior::dealDamage(%this, %amount, %victim)
+{
+    %takesDamage = %victim.getBehavior("TakesDamageBehavior");
+
+    if (!isObject(%takesDamage))
+        return;
+   
+    %takesDamage.takeDamage(%amount, %this);
+}
+
+//-----------------------------------------------------------------------------
+
+function DealsDamageBehavior::explode(%this, %position)
+{
+    if (%this.explodeEffect !$= "")
+    {
+        %particlePlayer = new ParticlePlayer();
+        %particlePlayer.BodyType = static;
+        %particlePlayer.SetPosition( %this.owner.getPosition() );
+        %particlePlayer.SceneLayer = %this.owner.getSceneLayer();
+        %particlePlayer.ParticleInterpolation = true;
+        %particlePlayer.Particle = %this.explodeEffect;
+        SandboxScene.add(%particlePlayer);
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+function DealsDamageBehavior::onCollision(%this, %object, %collisionDetails)
+{
+    %this.dealDamage(%this.strength, %object);
+   
+    if (%this.deleteOnHit)
+    {
+        %this.explode(getWords(%contacts, 0, 1));
+        %this.owner.safeDelete();
+    }
+}

+ 59 - 0
modules/LeapToy/1/scripts/SwapImageOnCollision.cs

@@ -0,0 +1,59 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+function LeapToy::createSwapImageBehavior( %this )
+{
+    if (!isObject(SwapImageOnCollisionBehavior))
+    {
+        %this.SwapImageBehavior = new BehaviorTemplate(SwapImageOnCollisionBehavior);
+
+        %this.SwapImageBehavior.friendlyName = "Swap Image On Collision";
+        %this.SwapImageBehavior.behaviorType = "Effects";
+        %this.SwapImageBehavior.description  = "Switches the image of an object when it collides";
+
+        %this.SwapImageBehavior.addBehaviorField(image, "The image to swap to", asset, "", ImageAsset);
+        %this.SwapImageBehavior.addBehaviorField(frame, "The frame of the image to swap to", int, 0);
+        %this.add(%this.SwapImageBehavior);
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+function SwapImageOnCollisionBehavior::initialize(%this, %image, %frame)
+{
+    %this.image = %image;
+    %this.frame = %frame;
+}
+
+//-----------------------------------------------------------------------------
+
+function SwapImageOnCollisionBehavior::onBehaviorAdd(%this)
+{
+   %this.owner.collisionCallback = true;
+}
+
+//-----------------------------------------------------------------------------
+
+function SwapImageOnCollisionBehavior::onCollision(%this, %object, %collisionDetails)
+{
+   %this.owner.setImage(%this.image, %this.frame);
+}

+ 133 - 0
modules/LeapToy/1/scripts/TakesDamageBehavior.cs

@@ -0,0 +1,133 @@
+//-----------------------------------------------------------------------------
+// Torque
+// Copyright GarageGames, LLC 2013
+//-----------------------------------------------------------------------------
+
+function LeapToy::createTakesDamageBehavior( %this )
+{
+    if (!isObject(TakesDamageBehavior))
+    {
+        %this.TakesDamageBehavior = new BehaviorTemplate(TakesDamageBehavior);
+        
+        %this.TakesDamageBehavior.friendlyName = "Takes Damage Advanced";
+        %this.TakesDamageBehavior.behaviorType = "Game";
+        %this.TakesDamageBehavior.description  = "Set the object to take damage from DealsDamage objects that collide with it";
+
+        %this.TakesDamageBehavior.addBehaviorField(health, "The amount of health the object has", int, 10);
+        %this.TakesDamageBehavior.addBehaviorField(lives, "The number of times the object can lose all its health", int, 3);
+        %this.TakesDamageBehavior.addBehaviorField(respawnTime, "The time between death and respawn (seconds)", float, 2.0);
+        %this.TakesDamageBehavior.addBehaviorField(invincibleTime, "The time after spawning before damage is applied (seconds)", float, 1.0);
+        %this.TakesDamageBehavior.addBehaviorField(respawnEffect, "The particle effect to play on spawn", asset, "", ParticleAsset);
+        %this.TakesDamageBehavior.addBehaviorField(explodeEffect, "The particle effect to play on death", asset, "", ParticleAsset);
+        
+        %this.add(%this.TakesDamageBehavior);
+    }    
+}
+
+//-----------------------------------------------------------------------------
+
+function TakesDamageBehavior::initialize(%this, %health, %lives, %respawnTime, %invincibleTime, %respawnEffect, %explodeEffect, %startFrame)
+{
+    %this.health = %health;
+    %this.lives = %lives;
+    %this.respawnTime = %respawnTime;
+    %this.invincibleTime = %invincibleTime;
+    %this.respawnEffect = %respawnEffect;
+    %this.explodeEffect = %explodeEffect;
+    %this.startFrame = %startFrame;
+    %this.startHealth = %this.health;
+}
+
+//-----------------------------------------------------------------------------
+
+function TakesDamageBehavior::onBehaviorAdd( %this )
+{
+    %this.startHealth = %this.health;    
+    %this.owner.collisionCallback = true;
+    %this.spawn();
+}
+
+//-----------------------------------------------------------------------------
+
+function TakesDamageBehavior::takeDamage( %this, %amount, %assailant )
+{
+    if (%this.invincible)
+        return;
+   
+    %this.health -= %amount;
+    
+    if (%this.health <= 0)
+    {
+        // Explode and kill the object
+        %this.explode();
+        %this.kill();
+        return;
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+function TakesDamageBehavior::kill( %this )
+{
+    %this.lives--;
+    
+    if (%this.lives <= 0)
+    {
+        %this.owner.safeDelete();
+        return;
+    }
+
+    %this.invincible = true;
+    %this.owner.visible = false;
+    %this.owner.setCollisionSuppress(true);
+    %this.owner.collisionActiveReceive = false;
+    %this.schedule(%this.respawnTime * 1000, "spawn");
+}
+
+//-----------------------------------------------------------------------------
+
+function TakesDamageBehavior::setVincible(%this)
+{
+    %this.invincible = false;
+}
+
+//-----------------------------------------------------------------------------
+
+function TakesDamageBehavior::spawn( %this )
+{
+    %this.owner.collisionActiveReceive = true;
+    %this.schedule(%this.invincibleTime * 1000, "setVincible");
+    %this.health = %this.startHealth;
+    %this.owner.visible = true;
+    %this.owner.setCollisionSuppress(false);
+    %this.owner.setImageFrame(%this.startFrame);
+    
+    if (%this.respawnEffect !$= "")
+    {
+        %particlePlayer = new ParticlePlayer();
+        %particlePlayer.BodyType = static;
+        %particlePlayer.Size = "10";
+        %particlePlayer.SetPosition( %this.owner.getPosition() );
+        %particlePlayer.SceneLayer = %this.owner.getSceneLayer();
+        %particlePlayer.ParticleInterpolation = true;
+        %particlePlayer.Particle = %this.respawnEffect;
+        SandboxScene.add(%particlePlayer);
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+function TakesDamageBehavior::explode( %this )
+{
+    if (%this.explodeEffect !$= "")
+    {
+        %particlePlayer = new ParticlePlayer();
+        %particlePlayer.BodyType = static;
+        %particlePlayer.SetPosition( %this.owner.getPosition() );
+        %particlePlayer.SceneLayer = %this.owner.getSceneLayer();
+        %particlePlayer.ParticleInterpolation = true;
+        %particlePlayer.Particle = %this.explodeEffect;
+        %particlePlayer.SizeScale = 0.8;
+        SandboxScene.add(%particlePlayer);
+    }
+}

+ 198 - 0
modules/LeapToy/1/scripts/breakoutDemo.cs

@@ -0,0 +1,198 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+function LeapToy::createBreakoutLevel( %this )
+{    
+    // Create background.
+    %this.createBackground();
+    
+    // Create the ground.
+    %this.createGround();
+    
+    // Create the breakable bricks
+    %this.createBricks();
+    
+    %this.createPaddle();
+    
+    %this.createBreakOutBall();    
+    
+    // Se the gravity.
+    SandboxScene.setGravity( 0, 0);
+    
+    // Set the manipulation mode.
+    Sandbox.useManipulation( off );
+
+    // Swap action maps
+    GestureMap.pop();
+    FingerMap.pop();
+    BreakoutMap.push();
+    
+    // Create the help text scene
+    %helpText = new SimSet();
+    %helpText.add(new ScriptObject() { Text = "Roll your hand back and forth to control the paddle"; });
+    %helpText.add(new ScriptObject() { Text = " "; });
+    %helpText.add(new ScriptObject() { Text = "When a block is hit twice, it will be destroyed"; });
+    %helpText.add(new ScriptObject() { Text = " "; });
+    %helpText.add(new ScriptObject() { Text = "Press H to return to the demo."; });
+    %this.createHelpTextScene(%helpText);
+    %helpText.delete();
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::createBricks( %this )
+{
+    // Fetch the block count.
+    %brickCount = LeapToy.BrickRows;
+    %brickColumsn = LeapToy.BrickColumns;
+
+    // Sanity!
+    if ( %brickCount < 1 )
+    {
+        echo( "Cannot have a brick count count less than one." );
+        return;
+    }
+
+    // Set the block size.
+    %brickSize = LeapToy.BrickSize;
+
+    // Calculate a block building position.
+    %posx = %brickCount * %brickSize._0 * -1;
+    %posy = 3 + (%brickSize._1 * 0.5) + 3;
+
+    // Build the stack of blocks.
+    for( %stack = 0; %stack < %brickCount; %stack++ )
+    {
+        // Calculate the stack position.
+        %stackIndexCount = %brickCount;
+        
+        %stackX = %posX + ( %stack * %brickSize._0 );
+        %stackY = %posY + ( %stack * %brickSize._1 );
+
+        // Build the stack.
+        for ( %stackIndex = 0; %stackIndex < LeapToy.BrickColumns; %stackIndex++ )
+        {
+            // Calculate the block position.
+            %brickX = (%stackIndex*%brickSize._0)+%posx;
+            %brickY = %stackY;
+            %brickFrames = "0 2 4 6 8 10";
+            %randomNumber = getRandom(0, 5);
+            %frame = getWord(%brickFrames, %randomNumber);
+            
+            // Create the sprite.
+            %obj = new Sprite()
+            {
+                class = "Brick";
+            };            
+            
+            %obj.setPosition( %brickX, %brickY );
+            %obj.setSize( %brickSize );
+            %obj.setBodyType("Kinematic");
+            %obj.setImage( "LeapToy:objectsBricks", %frame );
+            %obj.setDefaultFriction( 1.0 );
+            %obj.createPolygonBoxCollisionShape( %brickSize );
+            %obj.CollisionCallback = true;
+            
+            %takesDamage = %this.TakesDamageBehavior.createInstance();
+            %takesDamage.initialize(20, 100, 10, 0, "", "LeapToy:blockFadeParticle", %frame);
+            
+            %obj.addBehavior(%takesDamage);
+            
+            %swapImage = %this.SwapImageBehavior.createInstance();
+            %swapImage.initialize("LeapToy:objectsBricks", %frame+1);
+            %obj.addBehavior(%swapImage);
+            
+            // Add to the scene.
+            SandboxScene.add( %obj );
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::createPaddle(%this)
+{
+    // Create the player paddle
+    %obj = new Sprite();
+    
+    %obj.setPosition( 0, -8);
+    %obj.setSize( 5, 2.5 );
+    %obj.setImage( "LeapToy:playerUfo");
+    %obj.setDefaultFriction( 0 );
+    %obj.createPolygonBoxCollisionShape( 4.8, 2.3);
+    %obj.CollisionCallback = true;
+    %obj.setFixedAngle( true );
+    %this.paddle = %obj;
+    
+    SandboxScene.add(%obj);
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::createBreakoutBall(%this)
+{
+    // Create the ball.
+    %ball = new Sprite()
+    {
+        class = "Ball";
+    };
+    
+    %ball.Position = "5 5";
+    %ball.Size = 2;
+    %ball.Image = "LeapToy:widgetBall";        
+    %ball.setDefaultDensity( 1 );
+    %ball.setDefaultRestitution( 1.0 );
+    %ball.setDefaultFriction(0);
+    %ball.createCircleCollisionShape( 0.8 );
+    %ball.CollisionCallback = true;
+    %ball.setLinearVelocity(-5, 20);
+    %ball.setPosition(-5, -5);
+    
+    %dealsDamage = %this.DealsDamageBehavior.createInstance();
+    %dealsDamage.initialize(10, false, "");
+    %ball.addBehavior(%dealsDamage);    
+    
+    %this.breakoutBall = %ball;
+    
+    // Add to the scene.
+    SandboxScene.add( %ball );
+}
+
+//-----------------------------------------------------------------------------
+
+function Ball::onCollision(%this, %object, %collisionDetails)
+{
+    %xVelocity = %this.getLinearVelocity()._0;
+    %yVelocity = %this.getLinearVelocity()._1;
+    
+    %newXVelocity = mClamp(%xVelocity, (LeapToy.maxBallSpeed*-1), LeapToy.maxBallSpeed);
+    %newYVelocity = mClamp(%yVelocity, (LeapToy.maxBallSpeed*-1), LeapToy.maxBallSpeed);
+    
+    %this.setLinearVelocity(%newXVelocity, %newYVelocity);
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::movePaddle(%this, %speed)
+{
+    %this.paddle.setLinearVelocity(%speed, 0);
+}

+ 286 - 0
modules/LeapToy/1/scripts/builderDemo.cs

@@ -0,0 +1,286 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+function LeapToy::createBuilderLevel( %this )
+{
+    // Create background.
+    %this.createBackground();
+
+    // Create the ground.
+    %this.createGround();
+
+    // Create the pyramid.
+    %this.createPyramid();
+
+    // Create circle gesture visual.
+    %this.createCircleSprite();
+
+    // Create circle gesture visual.
+    %this.createBuilderFingers();    
+
+    // Set the gravity.
+    SandboxScene.setGravity( 0, -9.8 );
+
+    // Set the manipulation mode.
+    Sandbox.useManipulation( off );
+
+    // Create the help text scene
+    %helpText = new SimSet();
+    %helpText.add(new ScriptObject() { Text = "Press TAB to toggle between Cursor and Finger control."; });
+    %helpText.add(new ScriptObject() { Text = " "; });
+    %helpText.add(new ScriptObject() { Text = "Finger Control: "; });
+    %helpText.add(new ScriptObject() { Text = "   Reach in to enable finger collision."; });
+    %helpText.add(new ScriptObject() { Text = "   Fingers will turn yellow when collision is enabled."; });
+    %helpText.add(new ScriptObject() { Text = " "; });
+    %helpText.add(new ScriptObject() { Text = "Cursor Control: "; });
+    %helpText.add(new ScriptObject() { Text = "   Key tap creates a new block."; });
+    %helpText.add(new ScriptObject() { Text = "   Circle Gesture selects blocks within the circle."; });
+    %helpText.add(new ScriptObject() { Text = "   Screen Tap deletes the selected blocks."; });
+    %helpText.add(new ScriptObject() { Text = " "; });
+    %helpText.add(new ScriptObject() { Text = "Press H to return to the demo."; });
+    %this.createHelpTextScene(%helpText);
+    %helpText.delete();
+
+    %this.CenterZ = 125;
+
+    // Swap action maps
+    FingerMap.pop();
+    BreakoutMap.pop();
+    GestureMap.pop();
+
+    // Enable builder map
+    BuilderMap.push();
+}
+
+function LeapToy::createBuilderBlock(%this, %position)
+{
+    // Set the block size.
+    %blockSize = LeapToy.BlockSize;
+
+    %blockFrames = "0 2 4 6";
+    %randomNumber = getRandom(0, 4);
+
+    // Create the sprite.
+    %obj = new Sprite()
+    {
+        class = "Block";
+        flipped = false;
+    };
+
+    %obj.setSceneLayer(3);
+    %obj.setPosition( %position.x, %position.y );
+    %obj.setSize( %blockSize );
+    %obj.setImage( "LeapToy:objectsBlocks" );
+    %obj.setImageFrame( getWord(%blockFrames, %randomNumber) );
+    %obj.setDefaultFriction( 1.0 );
+    %obj.createPolygonBoxCollisionShape( %blockSize, %blockSize );
+
+    // Add to the scene.
+    SandboxScene.add( %obj );
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Called when the user makes a circle with their finger(s)
+//
+// %id - Finger ID, based on the order the finger was added to the tracking
+// %progress - How much of the circle has been completed
+// %radius - Radius of the circle created by the user's motion
+// %isClockwise - Toggle based on the direction the user made the circle
+// %state - State of the gesture progress: 1: Started, 2: Updated, 3: Stopped
+function LeapToy::reactToCircleBuilder(%this, %id, %progress, %radius, %isClockwise, %state)
+{
+    if (!%this.enableCircleGesture)
+        return;
+
+    if (isLeapCursorControlled())
+    {
+        if (%progress > 0 && %state == 3)
+        {
+            %this.grabObjectsInCircle();
+            %this.schedule(300, "hideCircleSprite");
+        }
+        else if (%progress > 0 && %state != 3)
+        {
+            %this.showCircleSprite(%radius/5, %isClockwise);
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+// Called when the user makes a swipe with their finger(s)
+//
+// %id - Finger ID, based on the order the finger was added to the tracking
+// %state - State of the gesture progress: 1: Started, 2: Updated, 3: Stopped
+// %direction - 3 point vector based on the direction the finger swiped
+// %speed - How fast the user's finger moved. Values will be quite large
+function LeapToy::reactToSwipeBuilder(%this, %id, %state, %direction, %speed)
+{
+    if (!%this.enableSwipeGesture)
+        return;
+}
+
+//-----------------------------------------------------------------------------
+// Called when the user makes a screen tap gesture with their finger(s)
+//
+// %id - Finger ID, based on the order the finger was added to the tracking
+// %position - 3 point vector based on where the finger was located in "Leap Space"
+// %direction - 3 point vector based on the direction the finger motion
+function LeapToy::reactToScreenTapBuilder(%this, %id, %position, %direction)
+{
+    if (!%this.enableScreenTapGesture)
+        return;        
+    
+    %this.deleteSelectedObjects();
+}
+
+//-----------------------------------------------------------------------------
+// Called when the user makes a key tap gesture with their finger(s)
+//
+// %id - Finger ID, based on the order the finger was added to the tracking
+// %position - 3 point vector based on where the finger was located in "Leap Space"
+// %direction - 3 point vector based on the direction the finger tap
+function LeapToy::reactToKeyTapBuilder(%this, %id, %position, %direction)
+{
+    if (!%this.enableKeyTapGesture)
+        return;
+
+    if (isLeapCursorControlled())
+    {       
+       %worldPosition = SandboxWindow.getWorldPoint(Canvas.getCursorPos());
+       %this.createBuilderBlock(%worldPosition);
+    }
+}
+
+//-----------------------------------------------------------------------------
+// Constantly polling callback based on the finger position on a hand
+// %id - Ordered hand ID based on when it was added to the tracking device
+// %position - 3 point vector based on where the finger is located in "Leap Space"
+function LeapToy::trackFingerPosBuilder(%this, %ids, %fingersX, %fingersY, %fingersZ)
+{
+    if (!%this.enableFingerTracking)
+        return;
+
+    for(%i = 0; %i < getWordCount(%ids); %i++)
+    {
+        %id = getWord(%ids, %i);
+        
+        // The next two lines of code use projection. To use intersection
+        // comment out both lines, then uncomment the getPointFromIntersection call.
+        %position = getWord(%fingersX, %i) SPC getWord(%fingersY, %i) SPC getWord(%fingersZ, %i);
+        %screenPosition = getPointFromProjection(%position);
+        
+        // This uses intersection
+        //%screenPosition = getPointFromIntersection(%id);        
+
+        %worldPosition = SandboxWindow.getWorldPoint(%screenPosition);
+        %this.showFingerBuilder(%id, %worldPosition, %position.z);
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::showFingerBuilder(%this, %id, %worldPosition, %zpos)
+{
+    echo("Finger " SPC %id SPC ":" SPC %worldPosition);
+    
+    %finger = %this.fingers[%id];
+    
+    if (!isObject(%finger))
+        return;
+        
+    if (!%finger.visible)
+    {
+        %finger.visible = true;
+        %finger.setPosition(%worldPosition);
+        %this.movePosition[%id] = %worldPosition;
+    }
+    else
+    {
+       %distance = VectorSub(%finger.getPosition(), %worldPosition);
+       %finger.moveTo(%worldPosition, VectorLen(%distance) * 10, true, false);
+       %this.movePosition[%id] = %worldPosition;
+    }
+    
+    %size = 2;
+    if( %zpos > LeapToy.CenterZ )
+    {
+       %finger.setCollisionSuppress(true);
+       // set the size to be bigger to give the illusion it is in front of the play area
+       %size = (%zpos/LeapToy.CenterZ) * 2;
+       %finger.setBlendColor(1.0, 1.0, 1.0, 0.5);
+    }
+    else
+    {
+       %finger.setCollisionSuppress(false);
+       %finger.setBlendColor("Yellow");
+    }
+    
+    %finger.setSize(%size, %size);
+    %this.schedule(200, "checkFingerBuilder", %id, %worldPosition);
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::checkFingerBuilder(%this, %id, %worldPosition)
+{
+    %finger = %this.fingers[%id];
+    
+    // Likely no activity, since the device is sensitive
+    if (%this.movePosition[%id] $= %worldPosition)
+    {
+        %finger.visible = false;
+        %finger.setCollisionSuppress(true);
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::createBuilderFingers(%this)
+{
+    for (%i = 0; %i < 10; %i++)
+    {
+        %name = "Finger" @ %i;
+        
+        // Create the circle.
+        %finger = new Sprite();        
+        %finger.setName(%name);
+        %finger.Position = "-10 5";
+        
+        %finger.Size = 2;
+        %finger.Image = "LeapToy:circleThree";
+        %finger.Visible = false; 
+        %finger.createCircleCollisionShape(1.0, "0 0");  
+        %finger.FixedAngle = true;
+        %finger.setDefaultFriction(1.0, true);    
+        %finger.CollisionSuppress = true;
+        %finger.setSceneLayer(0);
+        %finger.setCollisionLayers("1 2 3 4 5");       
+        
+        %this.fingers[%i] = %finger;
+        
+        // Add to the scene.
+        SandboxScene.add( %finger );
+    }
+}
+

+ 112 - 0
modules/LeapToy/1/scripts/fingerDemo.cs

@@ -0,0 +1,112 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+function LeapToy::createFingerLevel( %this )
+{
+    // Create background.
+    %this.createBackground();
+    
+    // Create the ground.
+    %this.createGround();
+
+    // Create circles that will track the fingers    
+    %this.createFingerCircles();
+    
+    // Set the gravity.
+    SandboxScene.setGravity( 0, 0);
+    
+    // Set the manipulation mode.
+    Sandbox.useManipulation( off );
+
+    // Swap action maps
+    // Swap action maps
+    GestureMap.pop();
+    BreakoutMap.pop();
+    FingerMap.push();
+    
+    // Create the help text scene
+    %helpText = new SimSet();
+    %helpText.add(new ScriptObject() { Text = "This demo will track pointables."; });
+    %helpText.add(new ScriptObject() { Text = " "; });
+    %helpText.add(new ScriptObject() { Text = "Whenever the Leap Motion device detects a finger"; });    
+    %helpText.add(new ScriptObject() { Text = "or tool, a circle will appear on screen."; });
+    %helpText.add(new ScriptObject() { Text = " "; });
+    %helpText.add(new ScriptObject() { Text = "Press H to return to the demo."; });
+    %this.createHelpTextScene(%helpText);
+    %helpText.delete();
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::createFingerCircles(%this)
+{
+    for (%i = 0; %i < 10; %i++)
+    {
+        %name = "Finger" @ %i;
+        
+        // Create the circle.
+        %circle = new Sprite();        
+        %circle.setName(%name);
+        %circle.Position = "-10 5";
+        %circle.setBodyType("Kinematic");
+        %circle.Size = 5;
+        %circle.Image = "LeapToy:circleThree";
+        %circle.Visible = false;
+        %circle.AngularVelocity = 180;
+        
+        %this.fingers[%i] = %circle;
+        
+        // Add to the scene.
+        SandboxScene.add( %circle );
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::showFingerCircle(%this, %id, %worldPosition)
+{
+    echo("Finger " SPC %id SPC ":" SPC %worldPosition);
+    
+    %finger = %this.fingers[%id];
+    
+    if (!isObject(%finger))
+        return;
+        
+    if (!%finger.visible)
+    {
+        %finger.visible = true;
+    }
+    
+    %finger.setPosition(%worldPosition);
+    %this.schedule(100, "checkFingerActivity", %id, %worldPosition);
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::checkFingerActivity(%this, %id, %worldPosition)
+{
+    %finger = %this.fingers[%id];
+    
+    // Likely no activity, since the device is sensitive
+    if (%finger.position $= %worldPosition)
+        %finger.visible = false;
+}

+ 376 - 0
modules/LeapToy/1/scripts/gestureDemo.cs

@@ -0,0 +1,376 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+function LeapToy::createGesturesLevel( %this )
+{
+    // Create background.
+    %this.createBackground();
+    
+    // Create the ground.
+    %this.createGround();
+
+    // Create the pyramid.
+    %this.createPyramid();
+
+    // Create a ball.
+    %this.createBall();
+
+    // Create circle gesture visual.
+    %this.createCircleSprite();
+    
+    // Make sure no objects are still selected
+    %this.selectedObjects.clear();
+    
+    // Se the gravity.
+    SandboxScene.setGravity( 0, -9.8 );
+        
+    // Set the manipulation mode.
+    Sandbox.useManipulation( pull );
+    
+    // Swap action maps
+    FingerMap.pop();
+    BreakoutMap.pop();
+    GestureMap.push();
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::createPyramid( %this )
+{
+    // Fetch the block count.
+    %blockCount = LeapToy.BlockCount;
+
+    // Sanity!
+    if ( %blockCount < 2 )
+    {
+        echo( "Cannot have a pyramid block count less than two." );
+        return;
+    }
+
+    // Set the block size.
+    %blockSize = LeapToy.BlockSize;
+
+    // Calculate a block building position.
+    %posx = %blockCount * -0.5 * %blockSize;
+    %posy = -8.8 + (%blockSize * 0.5);
+
+    // Build the stack of blocks.
+    for( %stack = 0; %stack < %blockCount; %stack++ )
+    {
+        // Calculate the stack position.
+        %stackIndexCount = %blockCount - (%stack*2);
+        %stackX = %posX + ( %stack * %blockSize );
+        %stackY = %posY + ( %stack * %blockSize );
+
+        // Build the stack.
+        for ( %stackIndex = 0; %stackIndex < %stackIndexCount; %stackIndex++ )
+        {
+            // Calculate the block position.
+            %blockX = %stackX + (%stackIndex*%blockSize);
+            %blockY = %stackY;
+            %blockFrames = "0 2 4 6";
+            %randomNumber = getRandom(0, 4);
+            
+            // Create the sprite.
+            %obj = new Sprite()
+            {
+                class = "Block";
+                flipped = false;
+            };
+            
+            %obj.setSceneLayer(3);
+            %obj.setPosition( %blockX, %blockY );
+            %obj.setSize( %blockSize );
+            %obj.setImage( "LeapToy:objectsBlocks" );
+            %obj.setImageFrame( getWord(%blockFrames, %randomNumber) );
+            %obj.setDefaultFriction( 1.0 );
+            %obj.createPolygonBoxCollisionShape( %blockSize, %blockSize );
+            
+            // Add to the scene.
+            SandboxScene.add( %obj );
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::createBall( %this )
+{
+    // Create the ball.
+    %ball = new Sprite();
+    %ball.Position = "5 5";
+    %ball.Size = 4;
+    %ball.Image = "LeapToy:widgetBall";        
+    %ball.setDefaultDensity( 1 );
+    %ball.setDefaultRestitution( 0.5 );
+    %ball.createCircleCollisionShape( 1.8 );
+    %ball.CollisionCallback = true;
+    %this.ball = %ball;
+
+    // Add to the scene.
+    SandboxScene.add( %ball );
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::createCircleSprite( %this )
+{
+    // Create the circle.
+    %circle = new Sprite();
+    %circle.Position = "-10 5";
+    %circle.setBodyType("Kinematic");
+    %circle.Size = 5;
+    %circle.Image = "LeapToy:circleThree";
+    %circle.Visible = false;
+    %circle.AngularVelocity = 180;
+    %this.circleSprite = %circle;
+
+    // Add to the scene.
+    SandboxScene.add( %circle );
+}
+
+//-----------------------------------------------------------------------------
+// This will be callsed when the user makes a circle gesture with a Leap Motion
+//
+// %radius - How large the circle gesture was
+// %isClockwise - True if the motion was clockwise
+function LeapToy::showCircleSprite( %this, %radius, %isClockwise )
+{
+    // If it isn't currently visible, show it
+    if (!%this.circleSprite.visible)
+    {
+        %this.circleSprite.visible = true;
+        
+        // Find out where the cursor is currenty location
+        %worldPosition = SandboxWindow.getWorldPoint(Canvas.getCursorPos());
+        
+        // Move the circle to that spot. This should be where the circle
+        // gesture first started
+        %this.circleSprite.position = %worldPosition;
+    }
+        
+    // Resize the circle based on how big the radius was
+    %this.circleSprite.size = %radius;
+    
+    // Rotate to the right if the circle is clockwise, left otherwise
+    if (%isClockwise)
+        %this.circleSprite.AngularVelocity = -180;
+    else
+        %this.circleSprite.AngularVelocity = 180;
+}
+
+//-----------------------------------------------------------------------------
+// This will be called when the user stops making a circle gesture
+function LeapToy::hideCircleSprite( %this )
+{
+    // Hide the sprite
+    %this.circleSprite.visible = 0;
+}
+
+//-----------------------------------------------------------------------------
+// This will be called when either the hand position or hand rotation is being tracked
+//
+// %horizontalSpeed - How fast to move in the X-axis
+// %verticalSpeed - How fast to move in the Y-axis
+// %angularSpeed - How fast to rotate on the Z-axis
+function LeapToy::accelerateBall( %this, %horizontalSpeed, %verticalSpeed )
+{
+    %this.ball.setLinearVelocity(%horizontalSpeed, %verticalSpeed);
+}
+
+//-----------------------------------------------------------------------------
+// This is called when a user makes a swipe gesture with the Leap Motion
+//
+// %position - Where to spawn the asteroid
+// %direction - 3 point vector based on the direction the finger swiped
+// %speed - How fast the user's finger moved. Values will be quite large
+function LeapToy::createAsteroid( %this, %position, %direction, %speed )
+{
+    // Size of the asteroid.
+    %size = 3;
+    
+    // Reduce the speed of the swipe so it can be used for a reasonable
+    // velocity in T2D.
+    %reducedSpeed = mClamp((%speed / 8), 0, 55);
+    %velocity = vectorScale(%direction, %reducedSpeed);
+
+    // Create an asteroid.
+    %object = new Sprite()
+    {
+        class = "Asteroid";
+    };
+
+    %object.Position = %position;
+    %object.CollisionCallback = true;
+    %object.Size = %size;
+    %object.SceneLayer = 7;
+    %object.Image = "LeapToy:widgetFruit";
+    %object.setDefaultDensity( 3 );
+    %object.createCircleCollisionShape( %size * 0.4 );
+    %object.setLinearVelocity( %velocity._0, %velocity._1 );
+    %object.setAngularVelocity( getRandom(-90,90) );
+    %object.setLifetime( 10 );
+    SandboxScene.add( %object );
+
+    // Create fire trail.
+    %player = new ParticlePlayer();
+    %player.Particle = "LeapToy:digitalFire";
+    %player.Position = %object.Position;
+    %player.EmissionRateScale = 3;
+    %player.SizeScale = 2;
+    %player.SceneLayer = 0;
+    %player.setLifetime( 10 );
+    SandboxScene.add( %player );
+    %jointId = SandboxScene.createRevoluteJoint( %object, %player );
+    SandboxScene.setRevoluteJointLimit( %jointId, 0, 0 );
+
+    // Assign the trail to the asteroid, used for cleanup later
+    %object.Trail = %player;
+}
+
+//-----------------------------------------------------------------------------
+// Called when an object with a class of "Asteroid" collides with another body.
+// In this toy, it will delete the asteroid and create an explosion
+//
+// %object - What the asteroid collided with
+// %collisionDetails - Information about the collision
+function Asteroid::onCollision( %this, %object, %collisionDetails )
+{
+    // Create explosion.
+    %player = new ParticlePlayer();
+    %player.BodyType = static;
+    %player.Particle = "LeapToy:digitalExplosion";
+    %player.Position = %this.Position;
+    %player.SceneLayer = 0;
+    SandboxScene.add( %player );
+
+    %controller = new PointForceController();
+    %controller.setControlLayers( 3 ); // Only affect blocks.
+    %controller.Radius = 5;
+    %controller.Force = -65;
+    %controller.NonLinear = true;
+    %controller.LinearDrag = 0.1;
+    %controller.AngularDrag = 0;
+    SandboxScene.Controllers.add( %controller );
+
+    %controller.Position = %this.Position;
+    %id = %controller.getID();
+
+    // Delete the asteroid.
+    %this.Trail.LinearVelocity = 0;
+    %this.Trail.AngularVelocity = 0;
+    %this.Trail.safeDelete();
+    %this.safeDelete();
+
+    LeapToy.schedule(500, "deleteController", %controller);
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::deleteController(%this, %controller)
+{
+    SandboxScene.Controllers.remove(%controller);
+    %controller.delete();
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::grabObjectsInCircle( %this )
+{
+    %worldPosition = %this.circleSprite.getPosition();
+    %size = %this.circleSprite.getSize();
+
+    %radius = (%size._0 * 0.5);
+    echo("Radius:" SPC %radius);
+
+    %picked = SandboxScene.pickCircle(%worldPosition, %radius);
+
+    // Finish if nothing picked.
+    if ( %picked $= "" )
+        return;
+
+    // Fetch the pick count.
+    %pickCount = %picked.Count;
+
+    for( %n = 0; %n < %pickCount; %n++ )
+    {
+        // Fetch the picked object.
+        %pickedObject = getWord( %picked, %n );
+
+        // Skip if the object is static.
+        if ( %pickedObject.getBodyType() $= "static" || %pickedObject.getBodyType() $= "kinematic")
+            continue;
+        
+        if (%pickedObject.class $= "block")
+            %pickedObject.flipFrame();
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+function Block::flipFrame( %this )
+{
+    %currentFrame = %this.getImageFrame();
+    
+    if (%this.flipped == true)
+    {
+        %newFrame = %currentFrame - 1;
+        %this.flipped = false;
+        LeapToy.selectedObjects.remove(%this);
+    }
+    else
+    {
+        %newFrame = %currentFrame + 1;
+        %this.flipped = true;
+        LeapToy.selectedObjects.add(%this);
+    }
+
+    %this.setImageFrame(%newFrame);
+    
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::createNewBlock( %this )
+{
+    %worldPosition = SandboxWindow.getWorldPoint(Canvas.getCursorPos());
+
+    // Create the sprite.
+    %obj = new Sprite();
+    %obj.setPosition( %worldPosition );
+    %obj.setSize( LeapToy.blockSize );
+    %obj.setImage( "ToyAssets:blocks" );
+    %obj.setImageFrame( getRandom(0,55) );
+    %obj.setDefaultFriction( 1.0 );
+    %obj.createPolygonBoxCollisionShape( LeapToy.blockSize, LeapToy.blockSize );
+
+    // Add to the scene.
+    SandboxScene.add( %obj );
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::deleteSelectedObjects( %this )
+{
+    while (%this.selectedObjects.getCount() > 0)
+        %this.selectedObjects.getObject(0).delete();
+}

+ 88 - 0
modules/LeapToy/1/scripts/helpText.cs

@@ -0,0 +1,88 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+function LeapToy::createHelpTextScene(%this, %helptext)
+{
+    %this.clearHelpTextScene();
+      
+    %this.helpTextScene = new Scene(HelpTextScene);
+
+    // Create the background
+    %background = new Sprite();
+    %background.setSize( 40, 30 );
+    %background.setImage("ToyAssets:skyBackground");
+    %background.setSceneLayer(20);
+    HelpTextScene.add(%background);
+    
+    // Check if we have text
+    if (%helptext.getCount() > 0)
+    {
+        %startingy = 0 + ((%helptext.getCount()/2) *0.6);
+        %spacing = 0.75;
+        %textsize = 0.6;
+        
+        // Iterate through the text lines
+        for (%x = 0; %x < %helptext.getCount(); %x++)
+        {                  
+            %object = new ImageFont();         
+            %object.Image = "ToyAssets:Font";
+            %object.FontSize = %textsize SPC %textsize;
+            %object.TextAlignment = "Left";
+            %positiony = %startingy - (%x * %spacing);
+            %object.Position = "-17" SPC %positiony;
+            %object.Text = %helptext.getObject(%x).Text;
+            HelpTextScene.add(%object);
+        }
+        
+        // Since we had text let's put up the help prompt.
+        %helpPrompt = new ImageFont();       
+        %helpPrompt.Image = "ToyAssets:Font";
+        %helpPrompt.FontSize = "0.7 0.7";
+        %helpPrompt.TextAlignment = "Center";      
+        %helpPrompt.Position = "0 -12";
+        %helpPrompt.Text = "Press H for help";
+        SandboxScene.add(%helpPrompt);      
+    }   
+}
+
+function LeapToy::toggleHelpTextScene(%this, %val)
+{
+    if (!isObject(HelpTextScene) || !%val)
+        return;
+
+    if (SandboxWindow.getScene() $= %this.helpTextScene)
+        SandboxWindow.setScene(SandboxScene);    
+    else
+        SandboxWindow.setScene(HelpTextScene);    
+}
+
+function LeapToy::clearHelpTextScene(%this)
+{
+    if (!isObject(HelpTextScene))
+        return;
+
+    if (SandboxWindow.getScene() $= %this.helpTextScene)
+        SandboxWindow.setScene(SandboxScene);    
+
+    HelpTextScene.clear();
+    HelpTextScene.delete();
+}

+ 315 - 0
modules/LeapToy/1/scripts/input.cs

@@ -0,0 +1,315 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+function LeapToy::initializeInput( %this )
+{
+    // General toy action map
+    new ActionMap(ToyMap);
+    
+    // Gesture action map for sandbox
+    new ActionMap(GestureMap);
+    
+    // Absolute palm rotation/pos action map for breakout game
+    new ActionMap(BreakoutMap);
+    
+    // Absolute finger positioning for finger demo
+    new ActionMap(FingerMap);
+    
+    // action map for the builder demo game
+    new ActionMap(BuilderMap);
+    
+    // Create keyboard bindings
+    ToyMap.bindObj(keyboard, tab, toggleCursorMode, %this);
+    ToyMap.bindObj(keyboard, escape, showToolBox, %this);
+    // Help text binding
+    ToyMap.bindObj(keyboard, h, toggleHelpTextScene, %this);
+
+    // Debugging keybinds
+    ToyMap.bindObj(keyboard, space, simulateCircle, %this);
+    ToyMap.bindObj(keyboard, x, simulateKeytap, %this);
+    ToyMap.bindObj(keyboard, z, showParticle, %this);    
+    ToyMap.bindObj(keyboard, a, movePaddleLeft, %this);    
+    ToyMap.bindObj(keyboard, d, movePaddleRight, %this);    
+    
+    // Create Leap Motion gesture bindings
+    GestureMap.bindObj(leapdevice, circleGesture, reactToCircleGesture, %this);
+    GestureMap.bindObj(leapdevice, screenTapGesture, reactToScreenTapGesture, %this);
+    GestureMap.bindObj(leapdevice, swipeGesture, reactToSwipeGesture, %this);
+    GestureMap.bindObj(leapdevice, keyTapGesture, reactToKeyTapGesture, %this);
+    
+    // Create the Leap Motion hand/finger bindings
+    BreakoutMap.bindObj(leapdevice, leapHandRot, "D", %this.handRotDeadzone, trackHandRotation, %this);
+    FingerMap.bindObj(leapdevice, leapFingerPos, trackFingerPos, %this);
+    
+   // Create Leap Motion Builder Demo bindings
+    BuilderMap.bindObj(leapdevice, circleGesture, reactToCircleBuilder, %this);
+    BuilderMap.bindObj(leapdevice, screenTapGesture, reactToScreenTapBuilder, %this);
+    BuilderMap.bindObj(leapdevice, swipeGesture, reactToSwipeBuilder, %this);
+    BuilderMap.bindObj(leapdevice, keyTapGesture, reactToKeyTapBuilder, %this);
+    BuilderMap.bindObj(leapdevice, leapFingerPos, trackFingerPosBuilder, %this);
+
+    // Push the LeapMap to the stack, making it active
+    ToyMap.push();
+    
+    // Initialize the Leap Motion manager
+    initLeapMotionManager();
+    enableLeapMotionManager(true);
+    enableLeapCursorControl(true);
+    
+    configureLeapGesture("Gesture.Circle.MinProgress", 1);
+    configureLeapGesture("Gesture.ScreenTap.MinForwardVelocity", 0.1);
+    configureLeapGesture("Gesture.ScreenTap.MinDistance", 0.1);
+    configureLeapGesture("Gesture.KeyTap.MinDownVelocity", 20);
+    configureLeapGesture("Gesture.KeyTap.MinDistance", 1.0);
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::destroyInput(%this)
+{
+    FingerMap.pop();
+    FingerMap.delete();
+    
+    BreakoutMap.pop();
+    BreakoutMap.delete();
+    
+    GestureMap.pop();
+    GestureMap.delete();
+    
+    ToyMap.pop();
+    ToyMap.delete();
+    
+    BuilderMap.pop();
+    BuilderMap.delete();
+}
+
+//-----------------------------------------------------------------------------
+// Called when the user makes a circle with their finger(s)
+//
+// %id - Finger ID, based on the order the finger was added to the tracking
+// %progress - How much of the circle has been completed
+// %radius - Radius of the circle created by the user's motion
+// %isClockwise - Toggle based on the direction the user made the circle
+// %state - State of the gesture progress: 1: Started, 2: Updated, 3: Stopped
+function LeapToy::reactToCircleGesture(%this, %id, %progress, %radius, %isClockwise, %state)
+{
+    if (!%this.enableCircleGesture)
+        return;
+
+    if (%progress > 0 && %state == 3)
+    {
+        %this.grabObjectsInCircle();
+	    %this.schedule(300, "hideCircleSprite");
+    }
+    else if (%progress > 0 && %state != 3)
+    {
+        %this.showCircleSprite(%radius/5, %isClockwise);
+    }
+}
+
+//-----------------------------------------------------------------------------
+// Called when the user makes a swipe with their finger(s)
+//
+// %id - Finger ID, based on the order the finger was added to the tracking
+// %state - State of the gesture progress: 1: Started, 2: Updated, 3: Stopped
+// %direction - 3 point vector based on the direction the finger swiped
+// %speed - How fast the user's finger moved. Values will be quite large
+function LeapToy::reactToSwipeGesture(%this, %id, %state, %direction, %speed)
+{
+    if (!%this.enableSwipeGesture)
+        return;
+
+    %worldPosition = SandboxWindow.getWorldPoint(Canvas.getCursorPos());
+
+    if (isLeapCursorControlled())
+        %worldPosition = "0 0";
+
+    %this.createAsteroid(%worldPosition, %direction, %speed);
+}
+
+//-----------------------------------------------------------------------------
+// Called when the user makes a screen tap gesture with their finger(s)
+//
+// %id - Finger ID, based on the order the finger was added to the tracking
+// %position - 3 point vector based on where the finger was located in "Leap Space"
+// %direction - 3 point vector based on the direction the finger motion
+function LeapToy::reactToScreenTapGesture(%this, %id, %position, %direction)
+{
+    if (!%this.enableScreenTapGesture)
+        return;
+
+    %control = Canvas.getMouseControl();
+    %control.performClick();
+}
+
+//-----------------------------------------------------------------------------
+// Called when the user makes a key tap gesture with their finger(s)
+//
+// %id - Finger ID, based on the order the finger was added to the tracking
+// %position - 3 point vector based on where the finger was located in "Leap Space"
+// %direction - 3 point vector based on the direction the finger tap
+function LeapToy::reactToKeyTapGesture(%this, %id, %position, %direction)
+{
+    if (!%this.enableKeyTapGesture)
+        return;
+
+    %this.deleteSelectedObjects();
+}
+
+//-----------------------------------------------------------------------------
+// Constantly polling callback based on the palm position of a hand
+//
+// %id - Ordered hand ID based on when it was added to the tracking device
+// %position - 3 point vector based on where the hand is located in "Leap Space"
+function LeapToy::trackHandPosition(%this, %id, %position)
+{
+    echo("Hand " @ %id @ " - x:" SPC %position._0 SPC "y:" SPC %position._1 SPC "z:" SPC %position._2);
+}
+
+//-----------------------------------------------------------------------------
+// Constantly polling callback based on the palm rotation of a hand
+//
+// %id - Ordered hand ID based on when it was added to the tracking device
+// %rotation - 3 point vector based on the hand's rotation: "yaw pitch roll"
+function LeapToy::trackHandRotation(%this, %id, %rotation)
+{
+    if (isLeapCursorControlled() || !%this.enableHandRotation)
+        return;
+
+    // Grab the values. Only going to use roll in this demo
+    %roll = %rotation._2;
+
+    %this.movePaddle(%roll*-1);
+}
+
+//-----------------------------------------------------------------------------
+// Constantly polling callback based on the finger position on a hand
+// %id - Ordered hand ID based on when it was added to the tracking device
+// %position - 3 point vector based on where the finger is located in "Leap Space"
+function LeapToy::trackFingerPos(%this, %ids, %fingersX, %fingersY, %fingersZ)
+{
+    if (!%this.enableFingerTracking)
+        return;
+
+    for(%i = 0; %i < getWordCount(%ids); %i++)
+    {
+        %id = getWord(%ids, %i);
+
+        %position = getWord(%fingersX, %i) SPC getWord(%fingersY, %i) SPC getWord(%fingersZ, %i);
+        %screenPosition = getPointFromProjection(%position);
+        //%screenPosition = getPointFromIntersection(%id);
+
+        %worldPosition = SandboxWindow.getWorldPoint(%screenPosition);
+        %this.showFingerCircle(%id, %worldPosition);        
+    }
+}
+
+//-----------------------------------------------------------------------------
+// Flips a switch to activate/deactivate cursor control by the Leap Motion Manager
+function LeapToy::toggleCursorMode( %this, %val )
+{
+    if (!%val)
+        return;
+        
+    if (isLeapCursorControlled())
+        enableLeapCursorControl(false);
+    else
+        enableLeapCursorControl(true);
+}
+
+//-----------------------------------------------------------------------------
+// Shows the Sandbox tool box
+function LeapToy::showToolBox( %this, %val )
+{
+    if (%val)
+        toggleToolbox(true);
+}
+
+//-----------------------------------------------------------------------------
+// DEBUGGING FUNCTIONS
+function LeapToy::simulateCircle( %this, %val)
+{
+    if (%val)
+    {
+        %this.grabObjectsInCircle(2);
+    }
+}
+function LeapToy::simulateKeyTap( %this, %val )
+{
+    if (%val)
+    {
+        %this.deleteSelectedObjects();
+    }
+}
+
+function LeapToy::showParticle(%this)
+{
+    %worldPosition = SandboxWindow.getWorldPoint(Canvas.getCursorPos());
+    
+    %particlePlayer = new ParticlePlayer();
+    %particlePlayer.BodyType = static;
+    %particlePlayer.SetPosition( %worldPosition );
+    %particlePlayer.SceneLayer = 0;
+    %particlePlayer.ParticleInterpolation = true;
+    %particlePlayer.Particle = "LeapToy:blockFadeParticle";
+    %particlePlayer.SizeScale = 1;
+    SandboxScene.add( %particlePlayer ); 
+    %particlePlayer.setLifeTime(3);
+}
+
+function LeapToy::movePaddleLeft(%this, %val)
+{
+    if (%val)
+    {
+        %this.paddle.setLinearVelocity(%this.PaddleSpeed*-1, 0);
+    }
+    else
+    {
+        %this.paddle.setLinearVelocity(0, 0);
+    }
+}
+
+function LeapToy::movePaddleRight(%this, %val)
+{
+    if (%val)
+    {
+        %this.paddle.setLinearVelocity(%this.PaddleSpeed, 0);
+    }
+    else
+    {
+        %this.paddle.setLinearVelocity(0, 0);
+    }
+}
+
+function LeapToy::simulateFingerPositions(%this)
+{
+    %numFingers = getRandom(0, 9);
+    setRandomSeed(-1);
+    %randomPosition = getRandom(-10, 10) SPC getRandom(-10, 10);
+    for (%i = 0; %i < %numFingers; %i++)
+    {
+        %this.showFingerCircle(%i, %randomPosition);
+    }
+}
+
+// DEBUGGING FUNCTIONS
+//-----------------------------------------------------------------------------

+ 125 - 0
modules/LeapToy/1/scripts/toy.cs

@@ -0,0 +1,125 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+function LeapToy::createBackground( %this )
+{    
+    // Create the sprite.
+    %background = new Sprite();
+    
+    // Set the sprite as "static" so it is not affected by gravity.
+    %background.setBodyType( static );
+       
+    // Set the position.
+    %background.Position = "0 0";
+
+    // Set the size.        
+    %background.Size = "40 30";
+    
+    // Set to the furthest background layer.
+    %background.SceneLayer = 31;
+    
+    // Set an image.
+    %background.Image = "LeapToy:menuBackground";
+
+    %background.createEdgeCollisionShape( -20, -15, -20, 15 );
+    %background.createEdgeCollisionShape( 20, -15, 20, 15 );
+    %background.createEdgeCollisionShape( -20, 15, 20, 15 );
+
+    // Add the sprite to the scene.
+    SandboxScene.add( %background );
+    
+    %this.createCircles();
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::createCircles( %this )
+{
+    // Create the sprite.
+    %circleOne = new Sprite();
+    %circleTwo = new Sprite();
+    
+    // Set the sprite as "static" so it is not affected by gravity.
+    %circleOne.BodyType = "Kinematic";
+    %circleTwo.BodyType = "Kinematic";
+       
+    // Set the position.
+    %circleOne.Position = "15 10";
+    %circleTwo.Position = "15 10";
+    
+    // Set the size.        
+    %circleOne.Size = "15 15";
+    %circleTwo.Size = "15 15";
+    
+    // Set to the furthest background layer.
+    %circleOne.SceneLayer = 30;
+    %circleTwo.SceneLayer = 30;
+    
+    // Set an image.
+    %circleOne.Image = "LeapToy:complexCircle";
+    %circleTwo.Image = "LeapToy:simpleCircle";
+    
+    %circleOne.AngularVelocity = 15;
+    %circleTwo.AngularVelocity = -15;
+    
+    // Add the sprite to the scene.
+    SandboxScene.add( %circleOne );
+    SandboxScene.add( %circleTwo );
+}
+
+//-----------------------------------------------------------------------------
+
+function LeapToy::createGround( %this )
+{
+    // Create the ground
+    %ground = new Scroller();
+    %ground.setBodyType("static");
+    %ground.Image = "LeapToy:window";
+    %ground.setPosition(0, -12);
+    %ground.SceneLayer = 11;
+    %ground.setSize(LeapToy.GroundWidth, 6);
+    %ground.setRepeatX(LeapToy.GroundWidth / 40);   
+    %ground.createEdgeCollisionShape(LeapToy.GroundWidth/-2, 3, LeapToy.GroundWidth/2, 3);
+    SandboxScene.add(%ground);    
+}
+
+//-----------------------------------------------------------------------------
+// This will be called when the user presses the spacebar
+//
+// %val - Will be true if the event is down, false if it was released
+function LeapToy::pickSprite( %this, %val )
+{
+    // Find out where the cursor is located, then convert to world coordinates
+    %cursorPosition = Canvas.getCursorPos();
+    %worldPosition = SandboxWindow.getWorldPoint(%cursorPosition);
+    
+    // If true, force an onTouchDown for the Sandbox input listener
+    // If false, force an onTouchUp for the Sandbox input listener    
+    if (%val)
+    {
+        Sandbox.InputController.onTouchDown(0, %worldPosition);
+    }
+    else
+    {
+        Sandbox.InputController.onTouchUp(0, %worldPosition);
+    }
+}