Ver código fonte

- Adds initial support for Social API with Scoreloop impl for BlackBerry.
- Cleans up some PREPROCESSOR macros for consistency.
- Fixes a few warnings.

seanpaultaylor 12 anos atrás
pai
commit
fcff3fca77
39 arquivos alterados com 3219 adições e 1750 exclusões
  1. 5 0
      gameplay/.cproject
  2. 25 7
      gameplay/gameplay.vcxproj
  3. 57 0
      gameplay/gameplay.vcxproj.filters
  4. 1 1
      gameplay/src/Animation.h
  5. 17 2
      gameplay/src/Base.h
  6. 1 1
      gameplay/src/Curve.cpp
  7. 1 1
      gameplay/src/DebugNew.cpp
  8. 14 14
      gameplay/src/DebugNew.h
  9. 4 8
      gameplay/src/Game.cpp
  10. 2 7
      gameplay/src/Game.h
  11. 2 2
      gameplay/src/Game.inl
  12. 1 2
      gameplay/src/Image.cpp
  13. 8 8
      gameplay/src/Image.h
  14. 2 2
      gameplay/src/PhysicsController.cpp
  15. 2 2
      gameplay/src/Platform.h
  16. 2 3
      gameplay/src/PlatformAndroid.cpp
  17. 1630 1634
      gameplay/src/PlatformBlackBerry.cpp
  18. 1 1
      gameplay/src/PlatformLinux.cpp
  19. 1 1
      gameplay/src/PlatformMacOSX.mm
  20. 6 6
      gameplay/src/PlatformWindows.cpp
  21. 1 1
      gameplay/src/PlatformiOS.mm
  22. 5 5
      gameplay/src/Ref.cpp
  23. 2 2
      gameplay/src/Ref.h
  24. 18 0
      gameplay/src/SocialAchievement.cpp
  25. 58 0
      gameplay/src/SocialAchievement.h
  26. 46 0
      gameplay/src/SocialController.cpp
  27. 86 0
      gameplay/src/SocialController.h
  28. 17 0
      gameplay/src/SocialPlayer.cpp
  29. 40 0
      gameplay/src/SocialPlayer.h
  30. 18 0
      gameplay/src/SocialScore.cpp
  31. 52 0
      gameplay/src/SocialScore.h
  32. 90 0
      gameplay/src/SocialSession.h
  33. 52 0
      gameplay/src/SocialSessionListener.cpp
  34. 70 0
      gameplay/src/SocialSessionListener.h
  35. 9 1
      gameplay/src/gameplay.h
  36. 4 37
      gameplay/src/lua/lua_Game.cpp
  37. 1 2
      gameplay/src/lua/lua_Game.h
  38. 698 0
      gameplay/src/social/ScoreloopSocialSession.cpp
  39. 170 0
      gameplay/src/social/ScoreloopSocialSession.h

+ 5 - 0
gameplay/.cproject

@@ -24,6 +24,7 @@
 								<option id="com.qnx.qcc.option.compiler.defines.1481323494" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
 									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
 									<listOptionValue builtIn="false" value="BT_USE_NEON"/>
+									<listOptionValue builtIn="false" value="GP_USE_SOCIAL"/>
 								</option>
 								<option id="com.qnx.qcc.option.compiler.includePath.2133604142" name="Include Directories (-I)" superClass="com.qnx.qcc.option.compiler.includePath" valueType="includePath">
 									<listOptionValue builtIn="false" value="&quot;../../external-deps/lua/include&quot;"/>
@@ -87,6 +88,7 @@
 								<option id="com.qnx.qcc.option.compiler.defines.398688299" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
 									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
 									<listOptionValue builtIn="false" value="BT_USE_NEON"/>
+									<listOptionValue builtIn="false" value="GP_USE_SOCIAL"/>
 								</option>
 								<option id="com.qnx.qcc.option.compiler.includePath.1670164593" name="Include Directories (-I)" superClass="com.qnx.qcc.option.compiler.includePath" valueType="includePath">
 									<listOptionValue builtIn="false" value="&quot;../../external-deps/bullet/include&quot;"/>
@@ -145,6 +147,8 @@
 								<option id="com.qnx.qcc.option.compiler.security.1671403331" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="false" valueType="boolean"/>
 								<option id="com.qnx.qcc.option.compiler.defines.1863269886" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
 									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
+									<listOptionValue builtIn="false" value="BT_USE_NEON"/>
+									<listOptionValue builtIn="false" value="GP_USE_SOCIAL"/>
 								</option>
 								<option id="com.qnx.qcc.option.compiler.includePath.847642559" name="Include Directories (-I)" superClass="com.qnx.qcc.option.compiler.includePath" valueType="includePath">
 									<listOptionValue builtIn="false" value="&quot;../../external-deps/bullet/include&quot;"/>
@@ -215,4 +219,5 @@
 	</storageModule>
 	<storageModule moduleId="com.qnx.tools.ide.qde.core.QNXProjectProperties"/>
 	<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+	<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
 </cproject>

+ 25 - 7
gameplay/gameplay.vcxproj

@@ -318,6 +318,12 @@
     <ClCompile Include="src\ScriptController.cpp" />
     <ClCompile Include="src\ScriptTarget.cpp" />
     <ClCompile Include="src\Slider.cpp" />
+    <ClCompile Include="src\SocialController.cpp" />
+    <ClCompile Include="src\social\ScoreloopSocialAchievement.cpp" />
+    <ClCompile Include="src\social\ScoreloopSocialLeaderboard.cpp" />
+    <ClCompile Include="src\social\ScoreloopSocialPlayer.cpp" />
+    <ClCompile Include="src\social\ScoreloopSocialScore.cpp" />
+    <ClCompile Include="src\social\ScoreloopSocialSession.cpp" />
     <ClCompile Include="src\SpriteBatch.cpp" />
     <ClCompile Include="src\Technique.cpp" />
     <ClCompile Include="src\Terrain.cpp" />
@@ -599,6 +605,18 @@
     <ClInclude Include="src\ScriptController.h" />
     <ClInclude Include="src\ScriptTarget.h" />
     <ClInclude Include="src\Slider.h" />
+    <ClInclude Include="src\SocialAchievement.h" />
+    <ClInclude Include="src\SocialController.h" />
+    <ClInclude Include="src\SocialLeaderboard.h" />
+    <ClInclude Include="src\SocialPlayer.h" />
+    <ClInclude Include="src\SocialScore.h" />
+    <ClInclude Include="src\SocialSession.h" />
+    <ClInclude Include="src\SocialSessionListener.h" />
+    <ClInclude Include="src\social\ScoreloopSocialAchievement.h" />
+    <ClInclude Include="src\social\ScoreloopSocialLeaderboard.h" />
+    <ClInclude Include="src\social\ScoreloopSocialPlayer.h" />
+    <ClInclude Include="src\social\ScoreloopSocialScore.h" />
+    <ClInclude Include="src\social\ScoreloopSocialSession.h" />
     <ClInclude Include="src\SpriteBatch.h" />
     <ClInclude Include="src\Stream.h" />
     <ClInclude Include="src\Technique.h" />
@@ -914,7 +932,7 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>USE_BLACKBERRY_GAMEPAD;_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GP_USE_SOCIAL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>
       </RuntimeTypeInfo>
@@ -949,7 +967,7 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GAMEPLAY_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GP_USE_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -973,7 +991,7 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GAMEPLAY_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GP_USE_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -993,7 +1011,7 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>__BB10__;_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GAMEPLAY_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GP_USE_MEM_LEAK_DETECTION;GP_USE_SOCIAL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -1014,7 +1032,7 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GAMEPLAY_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GP_USE_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -1076,7 +1094,7 @@
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;GP_USE_SOCIAL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <AdditionalOptions>-mfpu=neon %(AdditionalOptions)</AdditionalOptions>
     </ClCompile>
@@ -1095,7 +1113,7 @@
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;GP_USE_SOCIAL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>

+ 57 - 0
gameplay/gameplay.vcxproj.filters

@@ -13,6 +13,9 @@
     <Filter Include="src\lua">
       <UniqueIdentifier>{21cf31c6-9c10-44cb-a864-d46a0e7bfe5e}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\social">
+      <UniqueIdentifier>{7bd5ee6c-c0cc-4ae3-b7a9-443fb391b944}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="src\Animation.cpp">
@@ -861,6 +864,24 @@
     <ClCompile Include="src\lua\lua_RenderStateStencilOperation.cpp">
       <Filter>src\lua</Filter>
     </ClCompile>
+    <ClCompile Include="src\SocialController.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\social\ScoreloopSocialAchievement.cpp">
+      <Filter>src\social</Filter>
+    </ClCompile>
+    <ClCompile Include="src\social\ScoreloopSocialLeaderboard.cpp">
+      <Filter>src\social</Filter>
+    </ClCompile>
+    <ClCompile Include="src\social\ScoreloopSocialPlayer.cpp">
+      <Filter>src\social</Filter>
+    </ClCompile>
+    <ClCompile Include="src\social\ScoreloopSocialScore.cpp">
+      <Filter>src\social</Filter>
+    </ClCompile>
+    <ClCompile Include="src\social\ScoreloopSocialSession.cpp">
+      <Filter>src\social</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Animation.h">
@@ -1709,6 +1730,42 @@
     <ClInclude Include="src\lua\lua_RenderStateStencilOperation.h">
       <Filter>src\lua</Filter>
     </ClInclude>
+    <ClInclude Include="src\SocialController.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\SocialSession.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\SocialAchievement.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\SocialLeaderboard.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\SocialPlayer.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\SocialSessionListener.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\SocialScore.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\social\ScoreloopSocialAchievement.h">
+      <Filter>src\social</Filter>
+    </ClInclude>
+    <ClInclude Include="src\social\ScoreloopSocialLeaderboard.h">
+      <Filter>src\social</Filter>
+    </ClInclude>
+    <ClInclude Include="src\social\ScoreloopSocialPlayer.h">
+      <Filter>src\social</Filter>
+    </ClInclude>
+    <ClInclude Include="src\social\ScoreloopSocialScore.h">
+      <Filter>src\social</Filter>
+    </ClInclude>
+    <ClInclude Include="src\social\ScoreloopSocialSession.h">
+      <Filter>src\social</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="src\Game.inl">

+ 1 - 1
gameplay/src/Animation.h

@@ -227,7 +227,7 @@ private:
 
     AnimationController* _controller;       // The AnimationController that this Animation will run on.
     std::string _id;                        // The Animation's ID.
-    unsigned long _duration;              // the length of the animation (in milliseconds).
+    unsigned long _duration;                // the length of the animation (in milliseconds).
     std::vector<Channel*> _channels;        // The channels within this Animation.
     AnimationClip* _defaultClip;            // The Animation's default clip.
     std::vector<AnimationClip*>* _clips;    // All the clips created from this Animation.

+ 17 - 2
gameplay/src/Base.h

@@ -280,13 +280,28 @@ typedef GLuint FrameBufferHandle;
 typedef GLuint RenderBufferHandle;
 
 /** Gamepad handle definitions vary by platform. */
-#if defined(__QNX__) && defined(USE_BLACKBERRY_GAMEPAD)
+#if defined(__QNX__) && defined(GP_USE_GAMEPAD)
     typedef screen_device_t GamepadHandle;
-#elif defined(USE_XINPUT)
+#elif defined(WIN32)
     typedef unsigned long GamepadHandle;
 #else
     typedef unsigned int GamepadHandle;
 #endif
+
+#if defined(__QNX__) && defined(GP_USE_SOCIAL)
+    typedef void* SocialPlayerHandle;
+    typedef void* SocialAchievementHandle;
+    typedef void* SocialScoreHandle;
+#elif defined(WIN32)
+    typedef unsigned long SocialPlayerHandle;
+    typedef unsigned long SocialAchievementHandle;
+    typedef unsigned long SocialScoreHandle;
+#else
+    typedef unsigned int SocialPlayerHandle;
+    typedef unsigned int SocialAchievementHandle;
+    typedef unsigned int SocialScoreHandle;
+#endif
+
 }
 
 /**

+ 1 - 1
gameplay/src/Curve.cpp

@@ -110,7 +110,7 @@ Curve::~Curve()
 }
 
 Curve::Point::Point()
-    : time(0.0f), value(NULL), inValue(NULL), outValue(NULL)
+    : time(0.0f), value(NULL), inValue(NULL), outValue(NULL), type(LINEAR)
 {
 }
 

+ 1 - 1
gameplay/src/DebugNew.cpp

@@ -1,4 +1,4 @@
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 
 #include <new>
 #include <exception>

+ 14 - 14
gameplay/src/DebugNew.h

@@ -4,9 +4,9 @@
 /**
  * Global overrides of the new and delete operators for memory tracking.
  * This file is only included when memory leak detection is explicitly
- * request via the pre-processor definition GAMEPLAY_MEM_LEAK_DETECTION.
+ * request via the pre-processor definition GP_USE_MEM_LEAK_DETECTION.
  */
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 
 #include <new>
 #include <exception>
@@ -42,7 +42,7 @@ void operator delete[] (void* p, const char* file, int line) throw();
 // 'new' before allocation and redefine it to our custom version afterwards (we support 0-2, 9 parameter constructors).
 template<typename T> T* bullet_new()
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 #undef new
     T* t = new T();
 #define new DEBUG_NEW
@@ -54,7 +54,7 @@ template<typename T> T* bullet_new()
 
 template<typename T, typename T1> T* bullet_new(const T1& t1)
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION 
+#ifdef GP_USE_MEM_LEAK_DETECTION 
 #undef new 
     T* t = new T(t1);
 #define new DEBUG_NEW
@@ -66,7 +66,7 @@ template<typename T, typename T1> T* bullet_new(const T1& t1)
 
 template<typename T, typename T1, typename T2> T* bullet_new(const T1& t1, const T2& t2)
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 #undef new
     T* t = new T(t1, t2);
 #define new DEBUG_NEW
@@ -78,7 +78,7 @@ template<typename T, typename T1, typename T2> T* bullet_new(const T1& t1, const
 
 template<typename T, typename T1, typename T2> T* bullet_new(T1& t1, const T2& t2)
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 #undef new
     T* t = new T(t1, t2);
 #define new DEBUG_NEW
@@ -91,7 +91,7 @@ template<typename T, typename T1, typename T2> T* bullet_new(T1& t1, const T2& t
 template<typename T, typename T1, typename T2, typename T3> 
 T* bullet_new(const T1& t1, const T2& t2, const T3& t3)
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 #undef new
     T* t = new T(t1, t2, t3);
 #define new DEBUG_NEW
@@ -104,7 +104,7 @@ T* bullet_new(const T1& t1, const T2& t2, const T3& t3)
 template<typename T, typename T1, typename T2, typename T3> 
 T* bullet_new(T1& t1, const T2& t2, const T3& t3)
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 #undef new
     T* t = new T(t1, t2, t3);
 #define new DEBUG_NEW
@@ -117,7 +117,7 @@ T* bullet_new(T1& t1, const T2& t2, const T3& t3)
 template<typename T, typename T1, typename T2, typename T3, typename T4> 
 T* bullet_new(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 #undef new
     T* t = new T(t1, t2, t3, t4);
 #define new DEBUG_NEW
@@ -130,7 +130,7 @@ T* bullet_new(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
 template<typename T, typename T1, typename T2, typename T3, typename T4> 
 T* bullet_new(T1& t1, const T2& t2, const T3& t3, const T4& t4)
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 #undef new
     T* t = new T(t1, t2, t3, t4);
 #define new DEBUG_NEW
@@ -143,7 +143,7 @@ T* bullet_new(T1& t1, const T2& t2, const T3& t3, const T4& t4)
 template<typename T, typename T1, typename T2, typename T3, typename T4> 
 T* bullet_new(T1& t1, T2& t2, const T3& t3, const T4& t4)
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 #undef new
     T* t = new T(t1, t2, t3, t4);
 #define new DEBUG_NEW
@@ -156,7 +156,7 @@ T* bullet_new(T1& t1, T2& t2, const T3& t3, const T4& t4)
 template<typename T, typename T1, typename T2, typename T3, typename T4, typename T5> 
 T* bullet_new(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5)
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 #undef new
     T* t = new T(t1, t2, t3, t4, t5);
 #define new DEBUG_NEW
@@ -169,7 +169,7 @@ T* bullet_new(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5&
 template<typename T, typename T1, typename T2, typename T3, typename T4, typename T5> 
 T* bullet_new(T1& t1, T2& t2, const T3& t3, const T4& t4, const T5& t5)
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 #undef new
     T* t = new T(t1, t2, t3, t4, t5);
 #define new DEBUG_NEW
@@ -182,7 +182,7 @@ T* bullet_new(T1& t1, T2& t2, const T3& t3, const T4& t4, const T5& t5)
 template<typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9> 
 T* bullet_new(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8, const T9& t9)
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 #undef new
     T* t = new T(t1, t2, t3, t4, t5, t6, t7, t8, t9);
 #define new DEBUG_NEW

+ 4 - 8
gameplay/src/Game.cpp

@@ -20,7 +20,7 @@ double Game::_pausedTimeTotal = 0.0;
 
 Game::Game()
     : _initialized(false), _state(UNINITIALIZED), _pausedCount(0),
-      _frameLastFPS(0), _frameCount(0), _frameRate(0),
+      _frameLastFPS(0), _frameCount(0), _frameRate(0), _width(0), _height(0),
       _clearDepth(1.0f), _clearStencil(0), _properties(NULL),
       _animationController(NULL), _audioController(NULL),
       _physicsController(NULL), _aiController(NULL), _audioListener(NULL),
@@ -38,7 +38,7 @@ Game::~Game()
     // Do not call any virtual functions from the destructor.
     // Finalization is done from outside this class.
     SAFE_DELETE(_timeEvents);
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
     Ref::printLeaks();
     printMemoryLeaks();
 #endif
@@ -252,13 +252,13 @@ void Game::resume()
 void Game::exit()
 {
     // Only perform a full/clean shutdown if FORCE_CLEAN_SHUTDOWN or
-    // GAMEPLAY_MEM_LEAK_DETECTION is defined. Every modern OS is able to
+    // GP_USE_MEM_LEAK_DETECTION is defined. Every modern OS is able to
     // handle reclaiming process memory hundreds of times faster than it
     // would take us to go through every pointer in the engine and release
     // them nicely. For large games, shutdown can end up taking long time,
     // so we'll just call ::exit(0) to force an instant shutdown.
 
-#if defined FORCE_CLEAN_SHUTDOWN || defined GAMEPLAY_MEM_LEAK_DETECTION
+#if defined FORCE_CLEAN_SHUTDOWN || defined GP_USE_MEM_LEAK_DETECTION
 
     // Schedule a call to shutdown rather than calling it right away.
 	// This handles the case of shutting down the script system from
@@ -456,10 +456,6 @@ AudioListener* Game::getAudioListener()
     return _audioListener;
 }
 
-void Game::menuEvent()
-{
-}
-
 void Game::keyEvent(Keyboard::KeyEvent evt, int key)
 {
 }

+ 2 - 7
gameplay/src/Game.h

@@ -264,11 +264,6 @@ public:
      * @return The audio listener for this game.
      */
     AudioListener* getAudioListener();
-
-    /**
-     * Menu callback on menu events for platforms with special menu keys or special platform gestures.
-     */
-    virtual void menuEvent();
     
     /**
      * Shows or hides the virtual keyboard (if supported).
@@ -528,7 +523,7 @@ public:
     inline void getAccelerometerValues(float* pitch, float* roll);
 
     /**
-     * Gets raw sensor values, if equipped, allowing a distinction between device acceleration
+     * Gets sensor values (raw), if equipped, allowing a distinction between device acceleration
      * and rotation rate. Returns zeros on platforms with no corresponding support. See also
      * hasAccelerometer() and getAccelerometerValues().
      *
@@ -539,7 +534,7 @@ public:
      * @param gyroY The y-coordinate of the raw gyroscope data.
      * @param gyroZ The z-coordinate of the raw gyroscope data.
      */
-    inline void getRawSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ);
+    inline void getSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ);
 
     /**
      * Gets the command line arguments.

+ 2 - 2
gameplay/src/Game.inl

@@ -131,9 +131,9 @@ inline void Game::getAccelerometerValues(float* pitch, float* roll)
     Platform::getAccelerometerValues(pitch, roll);
 }
 
-inline void Game::getRawSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
+inline void Game::getSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
 {
-    return Platform::getRawSensorValues(accelX, accelY, accelZ, gyroX, gyroY, gyroZ);
+    return Platform::getSensorValues(accelX, accelY, accelZ, gyroX, gyroY, gyroZ);
 }
 
 inline unsigned int Game::getGamepadCount() const

+ 1 - 2
gameplay/src/Image.cpp

@@ -137,9 +137,8 @@ Image* Image::create(unsigned int width, unsigned int height, Image::Format form
 	return image;
 }
 
-Image::Image()
+Image::Image() : _data(NULL), _format(RGB), _width(0), _height(0)
 {
-    // Unused
 }
 
 Image::~Image()

+ 8 - 8
gameplay/src/Image.h

@@ -24,7 +24,7 @@ public:
 
     /**
      * Creates an image from the image file at the given path.
-     * 
+     *
      * @param path The path to the image file.
      * @return The newly created image.
      * @script{create}
@@ -33,7 +33,7 @@ public:
 
 	/**
      * Creates an image from the data provided
-     * 
+     *
      * @param width The width of the image data.
 	 * @param height The height of the image data.
 	 * @param format The format of the image data.
@@ -45,7 +45,7 @@ public:
 
     /**
      * Gets the image's raw pixel data.
-     * 
+     *
      * @return The image's pixel data.
      * @script{ignore}
      */
@@ -53,21 +53,21 @@ public:
 
     /**
      * Gets the image's format.
-     * 
+     *
      * @return The image's format.
      */
     inline Format getFormat() const;
 
     /**
      * Gets the height of the image.
-     * 
+     *
      * @return The height of the image.
      */
     inline unsigned int getHeight() const;
-        
+
     /**
      * Gets the width of the image.
-     * 
+     *
      * @return The width of the image.
      */
     inline unsigned int getWidth() const;
@@ -91,8 +91,8 @@ private:
 
     unsigned char* _data;
     Format _format;
-    unsigned int _height;
     unsigned int _width;
+    unsigned int _height;
 };
 
 }

+ 2 - 2
gameplay/src/PhysicsController.cpp

@@ -7,11 +7,11 @@
 #include "Bundle.h"
 #include "Terrain.h"
 
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 #undef new
 #endif
 #include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 #define new DEBUG_NEW
 #endif
 

+ 2 - 2
gameplay/src/Platform.h

@@ -218,7 +218,7 @@ private:
     static void getAccelerometerValues(float* pitch, float* roll);
 
     /**
-     * Gets raw sensor values, if equipped, allowing a distinction between device acceleration
+     * Gets sensor values (raw), if equipped, allowing a distinction between device acceleration
      * and rotation rate. Returns zeros on platforms with no corresponding support. See also
      * hasAccelerometer() and getAccelerometerValues().
      *
@@ -229,7 +229,7 @@ private:
      * @param gyroY The y-coordinate of the raw gyroscope data.
      * @param gyroZ The z-coordinate of the raw gyroscope data.
      */
-    static void getRawSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ);
+    static void getSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ);
 
     /**
      * Gets the command line arguments.

+ 2 - 3
gameplay/src/PlatformAndroid.cpp

@@ -1189,8 +1189,7 @@ void Platform::setMultiSampling(bool enabled)
         return;
     }
 
-    //todo
-
+    // TODO
     __multiSampling = enabled;
 }
 
@@ -1254,7 +1253,7 @@ void Platform::getAccelerometerValues(float* pitch, float* roll)
     }
 }
 
-void Platform::getRawSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
+void Platform::getSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
 {
     if (accelX)
     {

+ 1630 - 1634
gameplay/src/PlatformBlackBerry.cpp

@@ -1,476 +1,476 @@
-#ifdef __QNX__
-
-#include "Base.h"
-#include "Platform.h"
-#include "FileSystem.h"
-#include "Game.h"
-#include "Form.h"
-#include "ScriptController.h"
-#include <unistd.h>
-#include <sys/keycodes.h>
-#include <screen/screen.h>
-#include <input/screen_helpers.h>
-#include <gestures/set.h>
-#include <gestures/swipe.h>
-#include <gestures/pinch.h>
-#include <gestures/tap.h>
-#include <bps/bps.h>
-#include <bps/event.h>
-#include <bps/screen.h>
-#include <bps/navigator.h>
-#include <bps/sensor.h>
-#include <bps/orientation.h>
-#include <bps/virtualkeyboard.h>
-
-#define TOUCH_COUNT_MAX     4
-
-using namespace std;
-
-int __argc = 0;
-char** __argv = 0;
-struct timespec __timespec;
-static double __timeStart;
-static double __timeAbsolute;
-static bool __vsync = WINDOW_VSYNC;
-static screen_context_t __screenContext;
-static screen_window_t __screenWindow;
-static screen_event_t __screenEvent;
-static int __screenWindowSize[2];
-static bool __screenFullscreen = false;
-static EGLDisplay __eglDisplay = EGL_NO_DISPLAY;
-static EGLContext __eglContext = EGL_NO_CONTEXT;
-static EGLSurface __eglSurface = EGL_NO_SURFACE;
-static EGLConfig __eglConfig = 0;
-static int __orientationAngle;
-static bool __multiTouch = false;
-static bool __multiSampling = false;
-static float __pitch;
-static float __roll;
-static float __accelRawX;
-static float __accelRawY;
-static float __accelRawZ;
-static float __gyroRawX;
-static float __gyroRawY;
-static float __gyroRawZ;
-static const char* __glExtensions;
-static struct gestures_set * __gestureSet;
-static bitset<3> __gestureEventsProcessed;
-static bool __gestureSwipeRecognized = false;
-PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL;
-PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays = NULL;
-PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays = NULL;
-PFNGLISVERTEXARRAYOESPROC glIsVertexArray = NULL;
-
-namespace gameplay
-{
-
-// Gets the Keyboard::Key enumeration constant that corresponds to the given QNX key code.
-static Keyboard::Key getKey(int qnxKeycode)
-{
-    switch (qnxKeycode)
-    {
-    case KEYCODE_SYSREQ:
-        return Keyboard::KEY_SYSREQ;
-    case KEYCODE_BREAK:
-        return Keyboard::KEY_BREAK;
-    case KEYCODE_MENU:
-        return Keyboard::KEY_MENU;
-    case KEYCODE_KP_ENTER:
-        return Keyboard::KEY_KP_ENTER;
-    case KEYCODE_PAUSE:
-        return Keyboard::KEY_PAUSE;
-    case KEYCODE_SCROLL_LOCK:
-        return Keyboard::KEY_SCROLL_LOCK;
-    case KEYCODE_PRINT:
-        return Keyboard::KEY_PRINT;
-    case KEYCODE_ESCAPE:
-        return Keyboard::KEY_ESCAPE;
-    case KEYCODE_BACKSPACE:
-        return Keyboard::KEY_BACKSPACE;
-    case KEYCODE_BACK_TAB:
-        return Keyboard::KEY_BACK_TAB;
-    case KEYCODE_TAB:
-        return Keyboard::KEY_TAB;
-    case KEYCODE_RETURN:
-        return Keyboard::KEY_RETURN;
-    case KEYCODE_CAPS_LOCK:
-        return Keyboard::KEY_CAPS_LOCK;
-    case KEYCODE_LEFT_SHIFT:
-    case KEYCODE_RIGHT_SHIFT:
-        return Keyboard::KEY_SHIFT;
-    case KEYCODE_LEFT_CTRL:
-    case KEYCODE_RIGHT_CTRL:
-        return Keyboard::KEY_CTRL;
-    case KEYCODE_LEFT_ALT:
-    case KEYCODE_RIGHT_ALT:
-        return Keyboard::KEY_ALT;
-    case KEYCODE_LEFT_HYPER:
-    case KEYCODE_RIGHT_HYPER:
-        return Keyboard::KEY_HYPER;
-    case KEYCODE_INSERT:
-        return Keyboard::KEY_INSERT;
-    case KEYCODE_HOME:
-        return Keyboard::KEY_HOME;
-    case KEYCODE_PG_UP:
-        return Keyboard::KEY_PG_UP;
-    case KEYCODE_DELETE:
-        return Keyboard::KEY_DELETE;
-    case KEYCODE_END:
-        return Keyboard::KEY_END;
-    case KEYCODE_PG_DOWN:
-        return Keyboard::KEY_PG_DOWN;
-    case KEYCODE_LEFT:
-        return Keyboard::KEY_LEFT_ARROW;
-    case KEYCODE_RIGHT:
-        return Keyboard::KEY_RIGHT_ARROW;
-    case KEYCODE_UP:
-        return Keyboard::KEY_UP_ARROW;
-    case KEYCODE_DOWN:
-        return Keyboard::KEY_DOWN_ARROW;
-    case KEYCODE_NUM_LOCK:
-        return Keyboard::KEY_NUM_LOCK;
-    case KEYCODE_KP_PLUS:
-        return Keyboard::KEY_KP_PLUS;
-    case KEYCODE_KP_MINUS:
-        return Keyboard::KEY_KP_MINUS;
-    case KEYCODE_KP_MULTIPLY:
-        return Keyboard::KEY_KP_MULTIPLY;
-    case KEYCODE_KP_DIVIDE:
-        return Keyboard::KEY_KP_DIVIDE;
-    case KEYCODE_KP_HOME:
-        return Keyboard::KEY_KP_HOME;
-    case KEYCODE_KP_UP:
-        return Keyboard::KEY_KP_UP;
-    case KEYCODE_KP_PG_UP:
-        return Keyboard::KEY_KP_PG_UP;
-    case KEYCODE_KP_LEFT:
-        return Keyboard::KEY_KP_LEFT;
-    case KEYCODE_KP_FIVE:
-        return Keyboard::KEY_KP_FIVE;
-    case KEYCODE_KP_RIGHT:
-        return Keyboard::KEY_KP_RIGHT;
-    case KEYCODE_KP_END:
-        return Keyboard::KEY_KP_END;
-    case KEYCODE_KP_DOWN:
-        return Keyboard::KEY_KP_DOWN;
-    case KEYCODE_KP_PG_DOWN:
-        return Keyboard::KEY_KP_PG_DOWN;
-    case KEYCODE_KP_INSERT:
-        return Keyboard::KEY_KP_INSERT;
-    case KEYCODE_KP_DELETE:
-        return Keyboard::KEY_KP_DELETE;
-    case KEYCODE_F1:
-        return Keyboard::KEY_F1;
-    case KEYCODE_F2:
-        return Keyboard::KEY_F2;
-    case KEYCODE_F3:
-        return Keyboard::KEY_F3;
-    case KEYCODE_F4:
-        return Keyboard::KEY_F4;
-    case KEYCODE_F5:
-        return Keyboard::KEY_F5;
-    case KEYCODE_F6:
-        return Keyboard::KEY_F6;
-    case KEYCODE_F7:
-        return Keyboard::KEY_F7;
-    case KEYCODE_F8:
-        return Keyboard::KEY_F8;
-    case KEYCODE_F9:
-        return Keyboard::KEY_F9;
-    case KEYCODE_F10:
-        return Keyboard::KEY_F10;
-    case KEYCODE_F11:
-        return Keyboard::KEY_F11;
-    case KEYCODE_F12:
-        return Keyboard::KEY_F12;
-    case KEYCODE_SPACE:
-        return Keyboard::KEY_SPACE;
-    case KEYCODE_RIGHT_PAREN:
-        return Keyboard::KEY_RIGHT_PARENTHESIS;
-    case KEYCODE_ZERO:
-        return Keyboard::KEY_ZERO;
-    case KEYCODE_EXCLAM:
-        return Keyboard::KEY_EXCLAM;
-    case KEYCODE_ONE:
-        return Keyboard::KEY_ONE;
-    case KEYCODE_AT:
-        return Keyboard::KEY_AT;
-    case KEYCODE_TWO:
-        return Keyboard::KEY_TWO;
-    case KEYCODE_NUMBER:
-        return Keyboard::KEY_NUMBER;
-    case KEYCODE_THREE:
-        return Keyboard::KEY_THREE;
-    case KEYCODE_DOLLAR:
-        return Keyboard::KEY_DOLLAR;
-    case KEYCODE_FOUR:
-        return Keyboard::KEY_FOUR;
-    case KEYCODE_PERCENT:
-        return Keyboard::KEY_PERCENT;
-    case KEYCODE_FIVE:
-        return Keyboard::KEY_FIVE;
-    case KEYCODE_CIRCUMFLEX:
-        return Keyboard::KEY_CIRCUMFLEX;
-    case KEYCODE_SIX:
-        return Keyboard::KEY_SIX;
-    case KEYCODE_AMPERSAND:
-        return Keyboard::KEY_AMPERSAND;
-    case KEYCODE_SEVEN:
-        return Keyboard::KEY_SEVEN;
-    case KEYCODE_ASTERISK:
-        return Keyboard::KEY_ASTERISK;
-    case KEYCODE_EIGHT:
-        return Keyboard::KEY_EIGHT;
-    case KEYCODE_LEFT_PAREN:
-        return Keyboard::KEY_LEFT_PARENTHESIS;
-    case KEYCODE_NINE:
-        return Keyboard::KEY_NINE;
-    case KEYCODE_EQUAL:
-        return Keyboard::KEY_EQUAL;
-    case KEYCODE_PLUS:
-        return Keyboard::KEY_PLUS;
-    case KEYCODE_LESS_THAN:
-        return Keyboard::KEY_LESS_THAN;
-    case KEYCODE_COMMA:
-        return Keyboard::KEY_COMMA;
-    case KEYCODE_UNDERSCORE:
-        return Keyboard::KEY_UNDERSCORE;
-    case KEYCODE_MINUS:
-        return Keyboard::KEY_MINUS;
-    case KEYCODE_GREATER_THAN:
-        return Keyboard::KEY_GREATER_THAN;
-    case KEYCODE_PERIOD:
-        return Keyboard::KEY_PERIOD;
-    case KEYCODE_COLON:
-        return Keyboard::KEY_COLON;
-    case KEYCODE_SEMICOLON:
-        return Keyboard::KEY_SEMICOLON;
-    case KEYCODE_QUESTION:
-        return Keyboard::KEY_QUESTION;
-    case KEYCODE_SLASH:
-        return Keyboard::KEY_SLASH;
-    case KEYCODE_GRAVE:
-        return Keyboard::KEY_GRAVE;
-    case KEYCODE_TILDE:
-        return Keyboard::KEY_TILDE;
-    case KEYCODE_LEFT_BRACE:
-        return Keyboard::KEY_LEFT_BRACE;
-    case KEYCODE_LEFT_BRACKET:
-        return Keyboard::KEY_LEFT_BRACKET;
-    case KEYCODE_BAR:
-        return Keyboard::KEY_BAR;
-    case KEYCODE_BACK_SLASH:
-        return Keyboard::KEY_BACK_SLASH;
-    case KEYCODE_RIGHT_BRACE:
-        return Keyboard::KEY_RIGHT_BRACE;
-    case KEYCODE_RIGHT_BRACKET:
-        return Keyboard::KEY_RIGHT_BRACKET;
-    case KEYCODE_QUOTE:
-        return Keyboard::KEY_QUOTE;
-    case KEYCODE_APOSTROPHE:
-        return Keyboard::KEY_APOSTROPHE;
-    case 0x20AC:
-        return Keyboard::KEY_EURO;
-    case KEYCODE_POUND_SIGN:
-        return Keyboard::KEY_POUND;
-    case KEYCODE_YEN_SIGN:
-        return Keyboard::KEY_YEN;
-    case KEYCODE_MIDDLE_DOT:
-        return Keyboard::KEY_MIDDLE_DOT;
-    case KEYCODE_CAPITAL_A:
-        return Keyboard::KEY_CAPITAL_A;
-    case KEYCODE_A:
-        return Keyboard::KEY_A;
-    case KEYCODE_CAPITAL_B:
-        return Keyboard::KEY_CAPITAL_B;
-    case KEYCODE_B:
-        return Keyboard::KEY_B;
-    case KEYCODE_CAPITAL_C:
-        return Keyboard::KEY_CAPITAL_C;
-    case KEYCODE_C:
-        return Keyboard::KEY_C;
-    case KEYCODE_CAPITAL_D:
-        return Keyboard::KEY_CAPITAL_D;
-    case KEYCODE_D:
-        return Keyboard::KEY_D;
-    case KEYCODE_CAPITAL_E:
-        return Keyboard::KEY_CAPITAL_E;
-    case KEYCODE_E:
-        return Keyboard::KEY_E;
-    case KEYCODE_CAPITAL_F:
-        return Keyboard::KEY_CAPITAL_F;
-    case KEYCODE_F:
-        return Keyboard::KEY_F;
-    case KEYCODE_CAPITAL_G:
-        return Keyboard::KEY_CAPITAL_G;
-    case KEYCODE_G:
-        return Keyboard::KEY_G;
-    case KEYCODE_CAPITAL_H:
-        return Keyboard::KEY_CAPITAL_H;
-    case KEYCODE_H:
-        return Keyboard::KEY_H;
-    case KEYCODE_CAPITAL_I:
-        return Keyboard::KEY_CAPITAL_I;
-    case KEYCODE_I:
-        return Keyboard::KEY_I;
-    case KEYCODE_CAPITAL_J:
-        return Keyboard::KEY_CAPITAL_J;
-    case KEYCODE_J:
-        return Keyboard::KEY_J;
-    case KEYCODE_CAPITAL_K:
-        return Keyboard::KEY_CAPITAL_K;
-    case KEYCODE_K:
-        return Keyboard::KEY_K;
-    case KEYCODE_CAPITAL_L:
-        return Keyboard::KEY_CAPITAL_L;
-    case KEYCODE_L:
-        return Keyboard::KEY_L;
-    case KEYCODE_CAPITAL_M:
-        return Keyboard::KEY_CAPITAL_M;
-    case KEYCODE_M:
-        return Keyboard::KEY_M;
-    case KEYCODE_CAPITAL_N:
-        return Keyboard::KEY_CAPITAL_N;
-    case KEYCODE_N:
-        return Keyboard::KEY_N;
-    case KEYCODE_CAPITAL_O:
-        return Keyboard::KEY_CAPITAL_O;
-    case KEYCODE_O:
-        return Keyboard::KEY_O;
-    case KEYCODE_CAPITAL_P:
-        return Keyboard::KEY_CAPITAL_P;
-    case KEYCODE_P:
-        return Keyboard::KEY_P;
-    case KEYCODE_CAPITAL_Q:
-        return Keyboard::KEY_CAPITAL_Q;
-    case KEYCODE_Q:
-        return Keyboard::KEY_Q;
-    case KEYCODE_CAPITAL_R:
-        return Keyboard::KEY_CAPITAL_R;
-    case KEYCODE_R:
-        return Keyboard::KEY_R;
-    case KEYCODE_CAPITAL_S:
-        return Keyboard::KEY_CAPITAL_S;
-    case KEYCODE_S:
-        return Keyboard::KEY_S;
-    case KEYCODE_CAPITAL_T:
-        return Keyboard::KEY_CAPITAL_T;
-    case KEYCODE_T:
-        return Keyboard::KEY_T;
-    case KEYCODE_CAPITAL_U:
-        return Keyboard::KEY_CAPITAL_U;
-    case KEYCODE_U:
-        return Keyboard::KEY_U;
-    case KEYCODE_CAPITAL_V:
-        return Keyboard::KEY_CAPITAL_V;
-    case KEYCODE_V:
-        return Keyboard::KEY_V;
-    case KEYCODE_CAPITAL_W:
-        return Keyboard::KEY_CAPITAL_W;
-    case KEYCODE_W:
-        return Keyboard::KEY_W;
-    case KEYCODE_CAPITAL_X:
-        return Keyboard::KEY_CAPITAL_X;
-    case KEYCODE_X:
-        return Keyboard::KEY_X;
-    case KEYCODE_CAPITAL_Y:
-        return Keyboard::KEY_CAPITAL_Y;
-    case KEYCODE_Y:
-        return Keyboard::KEY_Y;
-    case KEYCODE_CAPITAL_Z:
-        return Keyboard::KEY_CAPITAL_Z;
-    case KEYCODE_Z:
-        return Keyboard::KEY_Z;
-    default:
-        return Keyboard::KEY_NONE;
-    }
-}
-
-/**
- * Returns the unicode value from the given QNX key code value.
- * Some non-printable characters also have corresponding unicode values, such as backspace.
- *
- * @param qnxKeyCode The keyboard key code.
- *
- * @return The unicode value or 0 if the keycode did not represent a unicode key.
- */
-static int getUnicode(int qnxKeyCode)
-{
-    if (qnxKeyCode >= KEYCODE_PC_KEYS && qnxKeyCode <= UNICODE_PRIVATE_USE_AREA_LAST)
-    {
-        switch (qnxKeyCode)
-        {
-        case KEYCODE_BACKSPACE:
-            return 0x0008;
-        case KEYCODE_TAB:
-            return 0x0009;
-        case KEYCODE_KP_ENTER:
-        case KEYCODE_RETURN:
-            return 0x000A;
-        case KEYCODE_ESCAPE:
-            return 0x001B;
-        // Win32 doesn't consider delete to be a key char.
-        default:
-            return 0;
-        }
-    }
-    return qnxKeyCode;
-}
-
-extern void print(const char* format, ...)
-{
-    GP_ASSERT(format);
-    va_list argptr;
-    va_start(argptr, format);
-    vfprintf(stderr, format, argptr);
-    va_end(argptr);
-}
-
-EGLenum checkErrorEGL(const char* msg)
-{
-    GP_ASSERT(msg);
-    static const char* errmsg[] =
-    {
-        "EGL function failed",
-        "EGL is not initialized, or could not be initialized, for the specified display",
-        "EGL cannot access a requested resource",
-        "EGL failed to allocate resources for the requested operation",
-        "EGL fail to access an unrecognized attribute or attribute value was passed in an attribute list",
-        "EGLConfig argument does not name a valid EGLConfig",
-        "EGLContext argument does not name a valid EGLContext",
-        "EGL current surface of the calling thread is no longer valid",
-        "EGLDisplay argument does not name a valid EGLDisplay",
-        "EGL arguments are inconsistent",
-        "EGLNativePixmapType argument does not refer to a valid native pixmap",
-        "EGLNativeWindowType argument does not refer to a valid native window",
-        "EGL one or more argument values are invalid",
-        "EGLSurface argument does not name a valid surface configured for rendering",
-        "EGL power management event has occurred",
-    };
-    EGLenum error = eglGetError();
-    fprintf(stderr, "%s: %s\n", msg, errmsg[error - EGL_SUCCESS]);
-    return error;
-}
-
-void gesture_callback(gesture_base_t* gesture, mtouch_event_t* event, void* param, int async)
-{
-    switch (gesture->type)
-    {
-    case GESTURE_SWIPE:
-        {
-            if ( __gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) )
-            {
-                gesture_swipe_t* swipe = (gesture_swipe_t*)gesture;
-                if (!__gestureSwipeRecognized)
-                {
-                    Platform::gestureSwipeEventInternal(swipe->coords.x, swipe->coords.y, swipe->direction);
-                    __gestureSwipeRecognized = true;
-                }
-
-            }
-            break;
-        }
-
+#ifdef __QNX__
+
+#include "Base.h"
+#include "Platform.h"
+#include "FileSystem.h"
+#include "Game.h"
+#include "Form.h"
+#include "ScriptController.h"
+#include <unistd.h>
+#include <sys/keycodes.h>
+#include <screen/screen.h>
+#include <input/screen_helpers.h>
+#include <gestures/set.h>
+#include <gestures/swipe.h>
+#include <gestures/pinch.h>
+#include <gestures/tap.h>
+#include <bps/bps.h>
+#include <bps/event.h>
+#include <bps/screen.h>
+#include <bps/navigator.h>
+#include <bps/sensor.h>
+#include <bps/orientation.h>
+#include <bps/virtualkeyboard.h>
+
+#define TOUCH_COUNT_MAX     4
+
+using namespace std;
+
+int __argc = 0;
+char** __argv = 0;
+struct timespec __timespec;
+static double __timeStart;
+static double __timeAbsolute;
+static bool __vsync = WINDOW_VSYNC;
+static screen_context_t __screenContext;
+static screen_window_t __screenWindow;
+static screen_event_t __screenEvent;
+static int __screenWindowSize[2];
+static bool __screenFullscreen = false;
+static EGLDisplay __eglDisplay = EGL_NO_DISPLAY;
+static EGLContext __eglContext = EGL_NO_CONTEXT;
+static EGLSurface __eglSurface = EGL_NO_SURFACE;
+static EGLConfig __eglConfig = 0;
+static int __orientationAngle;
+static bool __multiTouch = false;
+static bool __multiSampling = false;
+static float __pitch;
+static float __roll;
+static float __accelRawX;
+static float __accelRawY;
+static float __accelRawZ;
+static float __gyroRawX;
+static float __gyroRawY;
+static float __gyroRawZ;
+static const char* __glExtensions;
+static struct gestures_set * __gestureSet;
+static bitset<3> __gestureEventsProcessed;
+static bool __gestureSwipeRecognized = false;
+PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL;
+PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays = NULL;
+PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays = NULL;
+PFNGLISVERTEXARRAYOESPROC glIsVertexArray = NULL;
+
+namespace gameplay
+{
+
+// Gets the Keyboard::Key enumeration constant that corresponds to the given QNX key code.
+static Keyboard::Key getKey(int qnxKeycode)
+{
+    switch (qnxKeycode)
+    {
+    case KEYCODE_SYSREQ:
+        return Keyboard::KEY_SYSREQ;
+    case KEYCODE_BREAK:
+        return Keyboard::KEY_BREAK;
+    case KEYCODE_MENU:
+        return Keyboard::KEY_MENU;
+    case KEYCODE_KP_ENTER:
+        return Keyboard::KEY_KP_ENTER;
+    case KEYCODE_PAUSE:
+        return Keyboard::KEY_PAUSE;
+    case KEYCODE_SCROLL_LOCK:
+        return Keyboard::KEY_SCROLL_LOCK;
+    case KEYCODE_PRINT:
+        return Keyboard::KEY_PRINT;
+    case KEYCODE_ESCAPE:
+        return Keyboard::KEY_ESCAPE;
+    case KEYCODE_BACKSPACE:
+        return Keyboard::KEY_BACKSPACE;
+    case KEYCODE_BACK_TAB:
+        return Keyboard::KEY_BACK_TAB;
+    case KEYCODE_TAB:
+        return Keyboard::KEY_TAB;
+    case KEYCODE_RETURN:
+        return Keyboard::KEY_RETURN;
+    case KEYCODE_CAPS_LOCK:
+        return Keyboard::KEY_CAPS_LOCK;
+    case KEYCODE_LEFT_SHIFT:
+    case KEYCODE_RIGHT_SHIFT:
+        return Keyboard::KEY_SHIFT;
+    case KEYCODE_LEFT_CTRL:
+    case KEYCODE_RIGHT_CTRL:
+        return Keyboard::KEY_CTRL;
+    case KEYCODE_LEFT_ALT:
+    case KEYCODE_RIGHT_ALT:
+        return Keyboard::KEY_ALT;
+    case KEYCODE_LEFT_HYPER:
+    case KEYCODE_RIGHT_HYPER:
+        return Keyboard::KEY_HYPER;
+    case KEYCODE_INSERT:
+        return Keyboard::KEY_INSERT;
+    case KEYCODE_HOME:
+        return Keyboard::KEY_HOME;
+    case KEYCODE_PG_UP:
+        return Keyboard::KEY_PG_UP;
+    case KEYCODE_DELETE:
+        return Keyboard::KEY_DELETE;
+    case KEYCODE_END:
+        return Keyboard::KEY_END;
+    case KEYCODE_PG_DOWN:
+        return Keyboard::KEY_PG_DOWN;
+    case KEYCODE_LEFT:
+        return Keyboard::KEY_LEFT_ARROW;
+    case KEYCODE_RIGHT:
+        return Keyboard::KEY_RIGHT_ARROW;
+    case KEYCODE_UP:
+        return Keyboard::KEY_UP_ARROW;
+    case KEYCODE_DOWN:
+        return Keyboard::KEY_DOWN_ARROW;
+    case KEYCODE_NUM_LOCK:
+        return Keyboard::KEY_NUM_LOCK;
+    case KEYCODE_KP_PLUS:
+        return Keyboard::KEY_KP_PLUS;
+    case KEYCODE_KP_MINUS:
+        return Keyboard::KEY_KP_MINUS;
+    case KEYCODE_KP_MULTIPLY:
+        return Keyboard::KEY_KP_MULTIPLY;
+    case KEYCODE_KP_DIVIDE:
+        return Keyboard::KEY_KP_DIVIDE;
+    case KEYCODE_KP_HOME:
+        return Keyboard::KEY_KP_HOME;
+    case KEYCODE_KP_UP:
+        return Keyboard::KEY_KP_UP;
+    case KEYCODE_KP_PG_UP:
+        return Keyboard::KEY_KP_PG_UP;
+    case KEYCODE_KP_LEFT:
+        return Keyboard::KEY_KP_LEFT;
+    case KEYCODE_KP_FIVE:
+        return Keyboard::KEY_KP_FIVE;
+    case KEYCODE_KP_RIGHT:
+        return Keyboard::KEY_KP_RIGHT;
+    case KEYCODE_KP_END:
+        return Keyboard::KEY_KP_END;
+    case KEYCODE_KP_DOWN:
+        return Keyboard::KEY_KP_DOWN;
+    case KEYCODE_KP_PG_DOWN:
+        return Keyboard::KEY_KP_PG_DOWN;
+    case KEYCODE_KP_INSERT:
+        return Keyboard::KEY_KP_INSERT;
+    case KEYCODE_KP_DELETE:
+        return Keyboard::KEY_KP_DELETE;
+    case KEYCODE_F1:
+        return Keyboard::KEY_F1;
+    case KEYCODE_F2:
+        return Keyboard::KEY_F2;
+    case KEYCODE_F3:
+        return Keyboard::KEY_F3;
+    case KEYCODE_F4:
+        return Keyboard::KEY_F4;
+    case KEYCODE_F5:
+        return Keyboard::KEY_F5;
+    case KEYCODE_F6:
+        return Keyboard::KEY_F6;
+    case KEYCODE_F7:
+        return Keyboard::KEY_F7;
+    case KEYCODE_F8:
+        return Keyboard::KEY_F8;
+    case KEYCODE_F9:
+        return Keyboard::KEY_F9;
+    case KEYCODE_F10:
+        return Keyboard::KEY_F10;
+    case KEYCODE_F11:
+        return Keyboard::KEY_F11;
+    case KEYCODE_F12:
+        return Keyboard::KEY_F12;
+    case KEYCODE_SPACE:
+        return Keyboard::KEY_SPACE;
+    case KEYCODE_RIGHT_PAREN:
+        return Keyboard::KEY_RIGHT_PARENTHESIS;
+    case KEYCODE_ZERO:
+        return Keyboard::KEY_ZERO;
+    case KEYCODE_EXCLAM:
+        return Keyboard::KEY_EXCLAM;
+    case KEYCODE_ONE:
+        return Keyboard::KEY_ONE;
+    case KEYCODE_AT:
+        return Keyboard::KEY_AT;
+    case KEYCODE_TWO:
+        return Keyboard::KEY_TWO;
+    case KEYCODE_NUMBER:
+        return Keyboard::KEY_NUMBER;
+    case KEYCODE_THREE:
+        return Keyboard::KEY_THREE;
+    case KEYCODE_DOLLAR:
+        return Keyboard::KEY_DOLLAR;
+    case KEYCODE_FOUR:
+        return Keyboard::KEY_FOUR;
+    case KEYCODE_PERCENT:
+        return Keyboard::KEY_PERCENT;
+    case KEYCODE_FIVE:
+        return Keyboard::KEY_FIVE;
+    case KEYCODE_CIRCUMFLEX:
+        return Keyboard::KEY_CIRCUMFLEX;
+    case KEYCODE_SIX:
+        return Keyboard::KEY_SIX;
+    case KEYCODE_AMPERSAND:
+        return Keyboard::KEY_AMPERSAND;
+    case KEYCODE_SEVEN:
+        return Keyboard::KEY_SEVEN;
+    case KEYCODE_ASTERISK:
+        return Keyboard::KEY_ASTERISK;
+    case KEYCODE_EIGHT:
+        return Keyboard::KEY_EIGHT;
+    case KEYCODE_LEFT_PAREN:
+        return Keyboard::KEY_LEFT_PARENTHESIS;
+    case KEYCODE_NINE:
+        return Keyboard::KEY_NINE;
+    case KEYCODE_EQUAL:
+        return Keyboard::KEY_EQUAL;
+    case KEYCODE_PLUS:
+        return Keyboard::KEY_PLUS;
+    case KEYCODE_LESS_THAN:
+        return Keyboard::KEY_LESS_THAN;
+    case KEYCODE_COMMA:
+        return Keyboard::KEY_COMMA;
+    case KEYCODE_UNDERSCORE:
+        return Keyboard::KEY_UNDERSCORE;
+    case KEYCODE_MINUS:
+        return Keyboard::KEY_MINUS;
+    case KEYCODE_GREATER_THAN:
+        return Keyboard::KEY_GREATER_THAN;
+    case KEYCODE_PERIOD:
+        return Keyboard::KEY_PERIOD;
+    case KEYCODE_COLON:
+        return Keyboard::KEY_COLON;
+    case KEYCODE_SEMICOLON:
+        return Keyboard::KEY_SEMICOLON;
+    case KEYCODE_QUESTION:
+        return Keyboard::KEY_QUESTION;
+    case KEYCODE_SLASH:
+        return Keyboard::KEY_SLASH;
+    case KEYCODE_GRAVE:
+        return Keyboard::KEY_GRAVE;
+    case KEYCODE_TILDE:
+        return Keyboard::KEY_TILDE;
+    case KEYCODE_LEFT_BRACE:
+        return Keyboard::KEY_LEFT_BRACE;
+    case KEYCODE_LEFT_BRACKET:
+        return Keyboard::KEY_LEFT_BRACKET;
+    case KEYCODE_BAR:
+        return Keyboard::KEY_BAR;
+    case KEYCODE_BACK_SLASH:
+        return Keyboard::KEY_BACK_SLASH;
+    case KEYCODE_RIGHT_BRACE:
+        return Keyboard::KEY_RIGHT_BRACE;
+    case KEYCODE_RIGHT_BRACKET:
+        return Keyboard::KEY_RIGHT_BRACKET;
+    case KEYCODE_QUOTE:
+        return Keyboard::KEY_QUOTE;
+    case KEYCODE_APOSTROPHE:
+        return Keyboard::KEY_APOSTROPHE;
+    case 0x20AC:
+        return Keyboard::KEY_EURO;
+    case KEYCODE_POUND_SIGN:
+        return Keyboard::KEY_POUND;
+    case KEYCODE_YEN_SIGN:
+        return Keyboard::KEY_YEN;
+    case KEYCODE_MIDDLE_DOT:
+        return Keyboard::KEY_MIDDLE_DOT;
+    case KEYCODE_CAPITAL_A:
+        return Keyboard::KEY_CAPITAL_A;
+    case KEYCODE_A:
+        return Keyboard::KEY_A;
+    case KEYCODE_CAPITAL_B:
+        return Keyboard::KEY_CAPITAL_B;
+    case KEYCODE_B:
+        return Keyboard::KEY_B;
+    case KEYCODE_CAPITAL_C:
+        return Keyboard::KEY_CAPITAL_C;
+    case KEYCODE_C:
+        return Keyboard::KEY_C;
+    case KEYCODE_CAPITAL_D:
+        return Keyboard::KEY_CAPITAL_D;
+    case KEYCODE_D:
+        return Keyboard::KEY_D;
+    case KEYCODE_CAPITAL_E:
+        return Keyboard::KEY_CAPITAL_E;
+    case KEYCODE_E:
+        return Keyboard::KEY_E;
+    case KEYCODE_CAPITAL_F:
+        return Keyboard::KEY_CAPITAL_F;
+    case KEYCODE_F:
+        return Keyboard::KEY_F;
+    case KEYCODE_CAPITAL_G:
+        return Keyboard::KEY_CAPITAL_G;
+    case KEYCODE_G:
+        return Keyboard::KEY_G;
+    case KEYCODE_CAPITAL_H:
+        return Keyboard::KEY_CAPITAL_H;
+    case KEYCODE_H:
+        return Keyboard::KEY_H;
+    case KEYCODE_CAPITAL_I:
+        return Keyboard::KEY_CAPITAL_I;
+    case KEYCODE_I:
+        return Keyboard::KEY_I;
+    case KEYCODE_CAPITAL_J:
+        return Keyboard::KEY_CAPITAL_J;
+    case KEYCODE_J:
+        return Keyboard::KEY_J;
+    case KEYCODE_CAPITAL_K:
+        return Keyboard::KEY_CAPITAL_K;
+    case KEYCODE_K:
+        return Keyboard::KEY_K;
+    case KEYCODE_CAPITAL_L:
+        return Keyboard::KEY_CAPITAL_L;
+    case KEYCODE_L:
+        return Keyboard::KEY_L;
+    case KEYCODE_CAPITAL_M:
+        return Keyboard::KEY_CAPITAL_M;
+    case KEYCODE_M:
+        return Keyboard::KEY_M;
+    case KEYCODE_CAPITAL_N:
+        return Keyboard::KEY_CAPITAL_N;
+    case KEYCODE_N:
+        return Keyboard::KEY_N;
+    case KEYCODE_CAPITAL_O:
+        return Keyboard::KEY_CAPITAL_O;
+    case KEYCODE_O:
+        return Keyboard::KEY_O;
+    case KEYCODE_CAPITAL_P:
+        return Keyboard::KEY_CAPITAL_P;
+    case KEYCODE_P:
+        return Keyboard::KEY_P;
+    case KEYCODE_CAPITAL_Q:
+        return Keyboard::KEY_CAPITAL_Q;
+    case KEYCODE_Q:
+        return Keyboard::KEY_Q;
+    case KEYCODE_CAPITAL_R:
+        return Keyboard::KEY_CAPITAL_R;
+    case KEYCODE_R:
+        return Keyboard::KEY_R;
+    case KEYCODE_CAPITAL_S:
+        return Keyboard::KEY_CAPITAL_S;
+    case KEYCODE_S:
+        return Keyboard::KEY_S;
+    case KEYCODE_CAPITAL_T:
+        return Keyboard::KEY_CAPITAL_T;
+    case KEYCODE_T:
+        return Keyboard::KEY_T;
+    case KEYCODE_CAPITAL_U:
+        return Keyboard::KEY_CAPITAL_U;
+    case KEYCODE_U:
+        return Keyboard::KEY_U;
+    case KEYCODE_CAPITAL_V:
+        return Keyboard::KEY_CAPITAL_V;
+    case KEYCODE_V:
+        return Keyboard::KEY_V;
+    case KEYCODE_CAPITAL_W:
+        return Keyboard::KEY_CAPITAL_W;
+    case KEYCODE_W:
+        return Keyboard::KEY_W;
+    case KEYCODE_CAPITAL_X:
+        return Keyboard::KEY_CAPITAL_X;
+    case KEYCODE_X:
+        return Keyboard::KEY_X;
+    case KEYCODE_CAPITAL_Y:
+        return Keyboard::KEY_CAPITAL_Y;
+    case KEYCODE_Y:
+        return Keyboard::KEY_Y;
+    case KEYCODE_CAPITAL_Z:
+        return Keyboard::KEY_CAPITAL_Z;
+    case KEYCODE_Z:
+        return Keyboard::KEY_Z;
+    default:
+        return Keyboard::KEY_NONE;
+    }
+}
+
+/**
+ * Returns the unicode value from the given QNX key code value.
+ * Some non-printable characters also have corresponding unicode values, such as backspace.
+ *
+ * @param qnxKeyCode The keyboard key code.
+ *
+ * @return The unicode value or 0 if the keycode did not represent a unicode key.
+ */
+static int getUnicode(int qnxKeyCode)
+{
+    if (qnxKeyCode >= KEYCODE_PC_KEYS && qnxKeyCode <= UNICODE_PRIVATE_USE_AREA_LAST)
+    {
+        switch (qnxKeyCode)
+        {
+        case KEYCODE_BACKSPACE:
+            return 0x0008;
+        case KEYCODE_TAB:
+            return 0x0009;
+        case KEYCODE_KP_ENTER:
+        case KEYCODE_RETURN:
+            return 0x000A;
+        case KEYCODE_ESCAPE:
+            return 0x001B;
+        // Win32 doesn't consider delete to be a key char.
+        default:
+            return 0;
+        }
+    }
+    return qnxKeyCode;
+}
+
+extern void print(const char* format, ...)
+{
+    GP_ASSERT(format);
+    va_list argptr;
+    va_start(argptr, format);
+    vfprintf(stderr, format, argptr);
+    va_end(argptr);
+}
+
+EGLenum checkErrorEGL(const char* msg)
+{
+    GP_ASSERT(msg);
+    static const char* errmsg[] =
+    {
+        "EGL function failed",
+        "EGL is not initialized, or could not be initialized, for the specified display",
+        "EGL cannot access a requested resource",
+        "EGL failed to allocate resources for the requested operation",
+        "EGL fail to access an unrecognized attribute or attribute value was passed in an attribute list",
+        "EGLConfig argument does not name a valid EGLConfig",
+        "EGLContext argument does not name a valid EGLContext",
+        "EGL current surface of the calling thread is no longer valid",
+        "EGLDisplay argument does not name a valid EGLDisplay",
+        "EGL arguments are inconsistent",
+        "EGLNativePixmapType argument does not refer to a valid native pixmap",
+        "EGLNativeWindowType argument does not refer to a valid native window",
+        "EGL one or more argument values are invalid",
+        "EGLSurface argument does not name a valid surface configured for rendering",
+        "EGL power management event has occurred",
+    };
+    EGLenum error = eglGetError();
+    fprintf(stderr, "%s: %s\n", msg, errmsg[error - EGL_SUCCESS]);
+    return error;
+}
+
+void gesture_callback(gesture_base_t* gesture, mtouch_event_t* event, void* param, int async)
+{
+    switch (gesture->type)
+    {
+    case GESTURE_SWIPE:
+        {
+            if ( __gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) )
+            {
+                gesture_swipe_t* swipe = (gesture_swipe_t*)gesture;
+                if (!__gestureSwipeRecognized)
+                {
+                    Platform::gestureSwipeEventInternal(swipe->coords.x, swipe->coords.y, swipe->direction);
+                    __gestureSwipeRecognized = true;
+                }
+
+            }
+            break;
+        }
+
     case GESTURE_PINCH:
         {
             if ( __gestureEventsProcessed.test(Gesture::GESTURE_PINCH) )
@@ -482,1164 +482,1160 @@ void gesture_callback(gesture_base_t* gesture, mtouch_event_t* event, void* para
                 Game::getInstance()->gesturePinchEvent(pinch->centroid.x, pinch->centroid.y, scale);
             }
             break;
-        }
-
-    case GESTURE_TAP:
-        {
-            if ( __gestureEventsProcessed.test(Gesture::GESTURE_TAP) )
-            {
-                gesture_tap_t* tap = (gesture_tap_t*)gesture;
-                Platform::gestureTapEventInternal(tap->touch_coords.x, tap->touch_coords.y);
-            }
-            break;
-        }
-
-    default:
-        break;
-
-    }
-}
-
-#ifdef USE_BLACKBERRY_GAMEPAD
-
-static const char* __vendorStrings[] =
-{
-    "SteelSeries",
-    "Nintendo",
-};
-
-static const char* __productStrings[] =
-{
-    "FREE",
-    "Wii Remote",
-};
-
-static const int __VIDs[] = {
-    0x1038,
-    0x057e,
-};
-
-static const int __PIDs[] = {
-    0x1412,
-    0x0306,
-};
-
-static const unsigned int __knownGamepads = 2;
-
-void queryGamepad(GamepadHandle handle, int* buttonCount, int* joystickCount, int* productId, int* vendorId, char* productString, char* vendorString)
-{
-    char id[128];
-    screen_get_device_property_iv(handle, SCREEN_PROPERTY_BUTTON_COUNT, buttonCount);
-    screen_get_device_property_cv(handle, SCREEN_PROPERTY_ID_STRING, 128, id);
-    screen_get_device_property_cv(handle, SCREEN_PROPERTY_PRODUCT, 64, productString);
-    screen_get_device_property_cv(handle, SCREEN_PROPERTY_VENDOR, 64, vendorString);
-
-    // Check for the existence of analog sticks.
-    int analogs[3];
-    if (!screen_get_device_property_iv(handle, SCREEN_PROPERTY_ANALOG0, analogs))
-    {
-    	++(*joystickCount);
-    }
-
-    if (!screen_get_device_property_iv(handle, SCREEN_PROPERTY_ANALOG1, analogs))
-    {
-    	++(*joystickCount);
-    }
-
-    // ID string format: A-BBBB-CCCC-D.D
-    // A is the device's index
-    // BBBB is the device's Vendor ID (in hexadecimal)
-    // CCCC is the device's Product ID (also in hexadecimal)
-    // D.D is the device's version number
-    char* token = strtok(id, "-");
-    token = strtok(NULL, "-");
-    if (token)
-    {
-	    *vendorId = strtol(token, NULL, 16);
-    }
-
-    token = strtok(NULL, "-");
-    if (token)
-    {
-        *productId = strtol(token, NULL, 16);
-    }
-
-    // For gamepads unknown to BB10,
-    // check VID and PID against gamepads known to gameplay.
-    if (strlen(productString) == 0 || strlen(vendorString) == 0)
-    {
-        for (unsigned int i = 0; i < __knownGamepads; ++i)
-        {
-            if (__VIDs[i] == *vendorId && __PIDs[i] == *productId)
-            {
-            	strcpy(vendorString, __vendorStrings[i]);
-                strcpy(productString, __productStrings[i]);
-            }
-        }
-    }
-}
-
-void Platform::pollGamepadState(Gamepad* gamepad)
-{
-	unsigned int buttons;
-    screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_BUTTONS, (int*)&buttons);
-	gamepad->setButtons(buttons);
-
-    unsigned int i;
-    for (i = 0; i < gamepad->_joystickCount; ++i)
-    {
-        GP_ASSERT(i < 2);
-
-        int analog[3];
-        switch (i)
-        {
-        case 0:
-            screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_ANALOG0, analog);
-            break;
-        case 1:
-            screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_ANALOG1, analog);
-            break;
-        }
-        
-        // So far we've tested two gamepads with analog sticks on BlackBerry:
-        // the SteelSeries FREE, and the iControlPad.
-        // Both return values between -128 and +127, with the y axis starting from
-        // the top at -128.
-        // 1 / 128 == 0.0078125f
-        // 1 / 127 == 0.0078740157480315f
-        float x = (float)analog[0];
-        float y = -(float)analog[1];
-        x *= (x < 0) ? 0.0078125f : 0.0078740157480315f;
-        y *= (y > 0) ? 0.0078125f : 0.0078740157480315f;
-
-		gamepad->setJoystickValue(i, x, y);
-    }
-
-    for (i = 0; i < gamepad->_triggerCount; ++i)
-    {
-        GP_ASSERT(i < 2);
-
-        int analog[3];
-        switch (i)
-        {
-        case 0:
-            screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_ANALOG0, analog);
-            break;
-        case 1:
-            screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_ANALOG1, analog);
-            break;
-        }
-
-        float value = (float)analog[2] * 0.0078125f;
-		gamepad->setTriggerValue(i, value);
-    }
-}
-#else
-void Platform::pollGamepadState(Gamepad* gamepad)
-{
-}
-#endif
-
-Platform::Platform(Game* game)
-    : _game(game)
-{
-}
-
-Platform::~Platform()
-{
-    if (__eglDisplay != EGL_NO_DISPLAY)
-    {
-        eglMakeCurrent(__eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    }
-
-    if (__eglSurface != EGL_NO_SURFACE)
-    {
-        eglDestroySurface(__eglDisplay, __eglSurface);
-        __eglSurface = EGL_NO_SURFACE;
-    }
-
-    if (__eglContext != EGL_NO_CONTEXT)
-    {
-        eglDestroyContext(__eglDisplay, __eglContext);
-        __eglContext = EGL_NO_CONTEXT;
-    }
-
-    if (__eglDisplay != EGL_NO_DISPLAY)
-    {
-        eglTerminate(__eglDisplay);
-        __eglDisplay = EGL_NO_DISPLAY;
-    }
-
-    if (__screenWindow)
-    {
-        screen_destroy_window(__screenWindow);
-        __screenWindow = NULL;
-    }
-
-    if (__screenEvent)
-    {
-        screen_destroy_event(__screenEvent);
-        __screenEvent = NULL;
-    }
-
-    if (__screenContext)
-    {
-        screen_destroy_context(__screenContext);
-        __screenContext = NULL;
-    }
-}
-
-Platform* Platform::create(Game* game, void* attachToWindow)
-{
-    FileSystem::setResourcePath("./app/native/");
-    Platform* platform = new Platform(game);
-
-    // Query game config
-    int samples = 0;
-    Properties* config = Game::getInstance()->getConfig()->getNamespace("window", true);
-    if (config)
-    {
-        samples = std::max(config->getInt("samples"), 0);
-    }
-
-    __gestureSet = gestures_set_alloc();
-    swipe_gesture_alloc(NULL, gesture_callback, __gestureSet);
-    pinch_gesture_alloc(NULL, gesture_callback, __gestureSet);
-    tap_gesture_alloc(NULL, gesture_callback, __gestureSet);
-
-    bps_initialize();
-
-    // Initialize navigator and orientation
-    static const int SENSOR_RATE = 25000; // (25000 microseconds = 40 Hz)
-    sensor_set_rate(SENSOR_TYPE_AZIMUTH_PITCH_ROLL, SENSOR_RATE);
-    sensor_set_rate(SENSOR_TYPE_ACCELEROMETER, SENSOR_RATE);
-    sensor_set_rate(SENSOR_TYPE_GYROSCOPE, SENSOR_RATE);
-    sensor_set_skip_duplicates(SENSOR_TYPE_AZIMUTH_PITCH_ROLL, true);
-    sensor_set_skip_duplicates(SENSOR_TYPE_ACCELEROMETER, true);
-    sensor_set_skip_duplicates(SENSOR_TYPE_GYROSCOPE, true);
-    sensor_request_events(SENSOR_TYPE_AZIMUTH_PITCH_ROLL);
-    sensor_request_events(SENSOR_TYPE_ACCELEROMETER);
-    sensor_request_events(SENSOR_TYPE_GYROSCOPE);
-    navigator_request_events(0);
-    navigator_rotation_lock(true);
-    __orientationAngle = atoi(getenv("ORIENTATION"));
-
-    int rc = 0;
-    int screenFormat = SCREEN_FORMAT_RGBA8888;
-#ifdef __X86__
-    int screenUsage = SCREEN_USAGE_OPENGL_ES2;
-#else
-    int screenUsage = SCREEN_USAGE_DISPLAY|SCREEN_USAGE_OPENGL_ES2; // Physical device copy directly into physical display
-#endif
-    int screenSwapInterval = WINDOW_VSYNC ? 1 : 0;
-    int screenTransparency = SCREEN_TRANSPARENCY_NONE;
-
-    char *width_str = getenv("WIDTH");
-    char *height_str = getenv("HEIGHT");
-
-    // Hard-coded to (0,0).
-    int windowPosition[] =
-    {
-        0, 0
-    };
-
-    EGLint eglConfigCount;
-
-    // Hard-coded to 32-bit/OpenGL ES 2.0.
-    // NOTE: EGL_SAMPLE_BUFFERS and EGL_SAMPLES MUST remain at the beginning of the attribute list
-    // since they are expected to be at indices 0-3 in config fallback code later.
-    EGLint eglConfigAttrs[] =
-    {
-        EGL_SAMPLE_BUFFERS,     samples > 0 ? 1 : 0,
-        EGL_SAMPLES,            samples,
-        EGL_RED_SIZE,           8,
-        EGL_GREEN_SIZE,         8,
-        EGL_BLUE_SIZE,          8,
-        EGL_ALPHA_SIZE,         8,
-        EGL_DEPTH_SIZE,         24,
-        EGL_STENCIL_SIZE,       8,
-        EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
-        EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
-        EGL_NONE
-    };
-    __multiSampling = samples > 0;
-
-    const EGLint eglContextAttrs[] =
-    {
-        EGL_CONTEXT_CLIENT_VERSION,    2,
-        EGL_NONE
-    };
-
-    const EGLint eglSurfaceAttrs[] =
-    {
-        EGL_RENDER_BUFFER,    EGL_BACK_BUFFER,
-        EGL_NONE
-    };
-
-    // Create the screen context.
-    rc = screen_create_context(&__screenContext, 0);
-    if (rc)
-    {
-        perror("screen_create_context");
-        goto error;
-    }
-
-    // Create the screen window.
-    rc = screen_create_window(&__screenWindow, __screenContext);
-    if (rc)
-    {
-        perror("screen_create_window");
-        goto error;
-    }
-
-    // Set/get any window properties.
-    rc = screen_set_window_property_iv(__screenWindow, SCREEN_PROPERTY_FORMAT, &screenFormat);
-    if (rc)
-    {
-        perror("screen_set_window_property_iv(SCREEN_PROPERTY_FORMAT)");
-        goto error;
-    }
-
-    rc = screen_set_window_property_iv(__screenWindow, SCREEN_PROPERTY_USAGE, &screenUsage);
-    if (rc)
-    {
-        perror("screen_set_window_property_iv(SCREEN_PROPERTY_USAGE)");
-        goto error;
-    }
-
-    if (width_str && height_str)
-    {
-        __screenWindowSize[0] = atoi(width_str);
-        __screenWindowSize[1] = atoi(height_str);
-    }
-    else
-    {
-        screen_display_t screen_display;
-        rc = screen_get_window_property_pv(__screenWindow, SCREEN_PROPERTY_DISPLAY, (void **)&screen_display);
-        if (rc)
-        {
-            perror("screen_get_window_property_pv(SCREEN_PROPERTY_DISPLAY)");
-            goto error;
-        }
-
-        screen_display_mode_t screen_mode;
-        rc = screen_get_display_property_pv(screen_display, SCREEN_PROPERTY_MODE, (void**)&screen_mode);
-        if (rc)
-        {
-            perror("screen_get_display_property_pv(SCREEN_PROPERTY_MODE)");
-            goto error;
-        }
-
-        int size[2];
-        rc = screen_get_window_property_iv(__screenWindow, SCREEN_PROPERTY_BUFFER_SIZE, size);
-        if (rc)
-        {
-            perror("screen_get_window_property_iv(SCREEN_PROPERTY_BUFFER_SIZE)");
-            goto error;
-        }
-
-        __screenWindowSize[0] = size[0];
-        __screenWindowSize[1] = size[1];
-
-        if ((__orientationAngle == 0) || (__orientationAngle == 180))
-        {
-            if (((screen_mode.width > screen_mode.height) && (size[0] < size[1])) ||
-                ((screen_mode.width < screen_mode.height) && (size[0] > size[1])))
-            {
-                __screenWindowSize[1] = size[0];
-                __screenWindowSize[0] = size[1];
-            }
-        }
-        else if ((__orientationAngle == 90) || (__orientationAngle == 270))
-        {
-            if (((screen_mode.width > screen_mode.height) && (size[0] > size[1])) ||
-                ((screen_mode.width < screen_mode.height) && (size[0] < size[1])))
-            {
-                __screenWindowSize[1] = size[0];
-                __screenWindowSize[0] = size[1];
-            }
-        }
-        else
-        {
-            perror("Navigator returned an unexpected orientation angle.");
-            goto error;
-        }
-
-
-        rc = screen_set_window_property_iv(__screenWindow, SCREEN_PROPERTY_ROTATION, &__orientationAngle);
-        if (rc)
-        {
-            perror("screen_set_window_property_iv(SCREEN_PROPERTY_ROTATION)");
-            goto error;
-        }
-    }
-
-    rc = screen_set_window_property_iv(__screenWindow, SCREEN_PROPERTY_BUFFER_SIZE, __screenWindowSize);
-    if (rc)
-    {
-        perror("screen_set_window_property_iv(SCREEN_PROPERTY_BUFFER_SIZE)");
-        goto error;
-    }
-
-    if (windowPosition[0] != 0 || windowPosition[1] != 0)
-    {
-        rc = screen_set_window_property_iv(__screenWindow, SCREEN_PROPERTY_POSITION, windowPosition);
-        if (rc)
-        {
-            perror("screen_set_window_property_iv(SCREEN_PROPERTY_POSITION)");
-            goto error;
-        }
-    }
-
-    rc = screen_set_window_property_iv(__screenWindow, SCREEN_PROPERTY_TRANSPARENCY, &screenTransparency);
-    if (rc)
-    {
-        perror("screen_set_window_property_iv(SCREEN_PROPERTY_TRANSPARENCY)");
-        goto error;
-    }
-
-    // Double buffered.
-    rc = screen_create_window_buffers(__screenWindow, 2);
-    if (rc)
-    {
-        perror("screen_create_window_buffers");
-        goto error;
-    }
-
-    // Create screen event object.
-    rc = screen_create_event(&__screenEvent);
-    if (rc)
-    {
-        perror("screen_create_event");
-        goto error;
-    }
-
-    // Request screen events.
-    screen_request_events(__screenContext);
-
-    // Get the EGL display and initialize.
-    __eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    if (__eglDisplay == EGL_NO_DISPLAY)
-    {
-        perror("eglGetDisplay");
-        goto error;
-    }
-    if (eglInitialize(__eglDisplay, NULL, NULL) != EGL_TRUE)
-    {
-        perror("eglInitialize");
-        goto error;
-    }
-
-    if (eglChooseConfig(__eglDisplay, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) != EGL_TRUE || eglConfigCount == 0)
-    {
-        bool success = false;
-        while (samples)
-        {
-            // Try lowering the MSAA sample count until we find a supported config
-            GP_WARN("Failed to find a valid EGL configuration with EGL samples=%d. Trying samples=%d instead.", samples, samples/2);
-            samples /= 2;
-            eglConfigAttrs[1] = samples > 0 ? 1 : 0;
-            eglConfigAttrs[3] = samples;
-            if (eglChooseConfig(__eglDisplay, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) == EGL_TRUE && eglConfigCount > 0)
-            {
-                success = true;
-                break;
-            }
-        }
-
-        __multiSampling = samples > 0;
-
-        if (!success)
-        {
-            checkErrorEGL("eglChooseConfig");
-            goto error;
-        }
-    }
-
-    __eglContext = eglCreateContext(__eglDisplay, __eglConfig, EGL_NO_CONTEXT, eglContextAttrs);
-    if (__eglContext == EGL_NO_CONTEXT)
-    {
-        checkErrorEGL("eglCreateContext");
-        goto error;
-    }
-
-    __eglSurface = eglCreateWindowSurface(__eglDisplay, __eglConfig, __screenWindow, eglSurfaceAttrs);
-    if (__eglSurface == EGL_NO_SURFACE)
-    {
-        checkErrorEGL("eglCreateWindowSurface");
-        goto error;
-    }
-
-    if (eglMakeCurrent(__eglDisplay, __eglSurface, __eglSurface, __eglContext) != EGL_TRUE)
-    {
-        checkErrorEGL("eglMakeCurrent");
-        goto error;
-    }
-
-    // Set vsync.
-    eglSwapInterval(__eglDisplay, screenSwapInterval);
-
-    // Initialize OpenGL ES extensions.
-    __glExtensions = (const char*)glGetString(GL_EXTENSIONS);
-
-    if (strstr(__glExtensions, "GL_OES_vertex_array_object") || strstr(__glExtensions, "GL_ARB_vertex_array_object"))
-    {
-        glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES");
-        glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES");
-        glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES");
-        glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES");
-    }
-
- #ifdef USE_BLACKBERRY_GAMEPAD
-
-    screen_device_t* screenDevs;
-
-    // Discover initial gamepad devices.
-    int count;
-    screen_get_context_property_iv(__screenContext, SCREEN_PROPERTY_DEVICE_COUNT, &count);
-    screenDevs = (screen_device_t*)calloc(count, sizeof(screen_device_t));
-    screen_get_context_property_pv(__screenContext, SCREEN_PROPERTY_DEVICES, (void**)screenDevs);
-
-	for (int i = 0; i < count; i++) 
-    {
-	    int type;
-        screen_get_device_property_iv(screenDevs[i], SCREEN_PROPERTY_TYPE, &type);
-
-        if (type == SCREEN_EVENT_GAMEPAD || type == SCREEN_EVENT_JOYSTICK)
-        {
-            int buttonCount = 0;
-            int joystickCount = 0;
-            int productId;
-            int vendorId;
-            char productString[64];
-            char vendorString[64];
-            queryGamepad(screenDevs[i], &buttonCount, &joystickCount, &productId, &vendorId, productString, vendorString);
-            Platform::gamepadEventConnectedInternal(screenDevs[i], buttonCount, joystickCount, 0, vendorId, productId, vendorString, productString);
-        }
-	}
-	free(screenDevs);
-#endif
-
-    return platform;
-
-error:
-
-    return NULL;
-}
-
-/**
- * Convert the timespec into milliseconds.
- */
-double timespec2millis(struct timespec *a)
-{
-    GP_ASSERT(a);
-    return (1000.0 * a->tv_sec) + (0.000001 * a->tv_nsec);
-}
-
-/**
- * Fires a mouse event or a touch event on the game.
- * If the mouse event is not consumed, a touch event is fired instead.
- *
- * @param mouseEvent The mouse event to fire.
- * @param touchEvent The touch event to fire.
- * @param x The x position of the touch in pixels.
- * @param y The y position of the touch in pixels.
- */
-void mouseOrTouchEvent(Mouse::MouseEvent mouseEvent, Touch::TouchEvent touchEvent, int x, int y)
-{
-    if (!gameplay::Platform::mouseEventInternal(mouseEvent, x, y, 0))
-    {
-        Platform::touchEventInternal(touchEvent, x, y, 0, true);
-    }
-}
-
-int Platform::enterMessagePump()
-{
-    GP_ASSERT(_game);
-
-    int rc;
-    int eventType;
-    int flags;
-    int value;
-    int position[2];
-    int domain;
-    mtouch_event_t touchEvent;
-    bool suspended = false;
-
-    // Get the initial time.
-    clock_gettime(CLOCK_REALTIME, &__timespec);
-    __timeStart = timespec2millis(&__timespec);
-    __timeAbsolute = 0L;
-
-    _game->run();
-
-    // Message loop.
-    while (true)
-    {
-        bps_event_t* event = NULL;
-        
-        while (true)
-        {
-            rc = bps_get_event(&event, 1);
-            GP_ASSERT(rc == BPS_SUCCESS);
-
-            if (event == NULL)
-                break;
-
-            domain = bps_event_get_domain(event);
-
-            if (domain == screen_get_domain())
-            {
-                __screenEvent = screen_event_get_event(event);
-                screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_TYPE, &eventType);
-                switch (eventType)
-                {
-                    case SCREEN_EVENT_MTOUCH_TOUCH:
-                    {
-                        screen_get_mtouch_event(__screenEvent, &touchEvent, 0);
-                        if (__gestureEventsProcessed.any())
-                            rc = gestures_set_process_event(__gestureSet, &touchEvent, NULL);
-
-                        if ( !rc && (__multiTouch || touchEvent.contact_id == 0) )
-                        {
-                            gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, touchEvent.x, touchEvent.y, touchEvent.contact_id);
-                        }
-                        break;
-                    }
-
-                    case SCREEN_EVENT_MTOUCH_RELEASE:
-                    {
-                        screen_get_mtouch_event(__screenEvent, &touchEvent, 0);
-                        if (__gestureEventsProcessed.any())
-                            rc = gestures_set_process_event(__gestureSet, &touchEvent, NULL);
-
-                        if ( !rc && (__multiTouch || touchEvent.contact_id == 0) )
-                        {
-                            gameplay::Platform::touchEventInternal(Touch::TOUCH_RELEASE, touchEvent.x, touchEvent.y, touchEvent.contact_id);
-                        }
-                        if (__gestureSwipeRecognized)
-                        {
-                            __gestureSwipeRecognized = false;
-                        }
-                        break;
-                    }
-
-                    case SCREEN_EVENT_MTOUCH_MOVE:
-                    {
-                        screen_get_mtouch_event(__screenEvent, &touchEvent, 0);
-                        if (__gestureEventsProcessed.any())
-                            rc = gestures_set_process_event(__gestureSet, &touchEvent, NULL);
-
-                        if ( !rc && (__multiTouch || touchEvent.contact_id == 0) )
-                        {
-                            gameplay::Platform::touchEventInternal(Touch::TOUCH_MOVE, touchEvent.x, touchEvent.y, touchEvent.contact_id);
-                        }
-                        break;
-                    }
-
-                    case SCREEN_EVENT_POINTER:
-                    {
-                        static int mouse_pressed = 0;
-                        int buttons;
-                        int wheel;
-                        // A move event will be fired unless a button state changed.
-                        bool move = true;
-                        bool left_move = false;
-                        // This is a mouse move event, it is applicable to a device with a usb mouse or simulator.
-                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_BUTTONS, &buttons);
-                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_SOURCE_POSITION, position);
-                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel);
-
-                        // Handle left mouse. Interpret as touch if the left mouse event is not consumed.
-                        if (buttons & SCREEN_LEFT_MOUSE_BUTTON)
-                        {
-                            if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON)
-                            {
-                                left_move = true;
-                            }
-                            else
-                            {
-                                move = false;
-                                mouse_pressed |= SCREEN_LEFT_MOUSE_BUTTON;
-                                mouseOrTouchEvent(Mouse::MOUSE_PRESS_LEFT_BUTTON, Touch::TOUCH_PRESS, position[0], position[1]);
-                            }
-                        }
-                        else if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON)
-                        {
-                            move = false;
-                            mouse_pressed &= ~SCREEN_LEFT_MOUSE_BUTTON;
-                            mouseOrTouchEvent(Mouse::MOUSE_RELEASE_LEFT_BUTTON, Touch::TOUCH_RELEASE, position[0], position[1]);
-                        }
-
-                        // Handle right mouse.
-                        if (buttons & SCREEN_RIGHT_MOUSE_BUTTON)
-                        {
-                            if ((mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON) == 0)
-                            {
-                                move = false;
-                                mouse_pressed |= SCREEN_RIGHT_MOUSE_BUTTON;
-                                gameplay::Platform::mouseEventInternal(Mouse::MOUSE_PRESS_RIGHT_BUTTON, position[0], position[1], 0);
-                            }
-                        }
-                        else if (mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON)
-                        {
-                            move = false;
-                            mouse_pressed &= ~SCREEN_RIGHT_MOUSE_BUTTON;
-                            gameplay::Platform::mouseEventInternal(Mouse::MOUSE_RELEASE_RIGHT_BUTTON, position[0], position[1], 0);
-                        }
-
-                        // Handle middle mouse.
-                        if (buttons & SCREEN_MIDDLE_MOUSE_BUTTON)
-                        {
-                            if ((mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON) == 0)
-                            {
-                                move = false;
-                                mouse_pressed |= SCREEN_MIDDLE_MOUSE_BUTTON;
-                                gameplay::Platform::mouseEventInternal(Mouse::MOUSE_PRESS_MIDDLE_BUTTON, position[0], position[1], 0);
-                            }
-                        }
-                        else if (mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON)
-                        {
-                            move = false;
-                            mouse_pressed &= ~SCREEN_MIDDLE_MOUSE_BUTTON;
-                            gameplay::Platform::mouseEventInternal(Mouse::MOUSE_RELEASE_MIDDLE_BUTTON, position[0], position[1], 0);
-                        }
-
-                        // Fire a move event if none of the buttons changed.
-                        if (left_move)
-                        {
-                            mouseOrTouchEvent(Mouse::MOUSE_MOVE, Touch::TOUCH_MOVE, position[0], position[1]);
-                        }
-                        else if (move)
-                        {
-                            gameplay::Platform::mouseEventInternal(Mouse::MOUSE_MOVE, position[0], position[1], 0);
-                        }
-
-                        // Handle mouse wheel events.
-                        if (wheel)
-                        {
-                            gameplay::Platform::mouseEventInternal(Mouse::MOUSE_WHEEL, position[0], position[1], -wheel);
-                        }
-                        break;
-                    }
-
-                    case SCREEN_EVENT_KEYBOARD:
-                    {
-                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_KEY_FLAGS, &flags);
-                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_KEY_SYM, &value);
-                        gameplay::Keyboard::KeyEvent evt = (flags & KEY_DOWN) ? gameplay::Keyboard::KEY_PRESS :  gameplay::Keyboard::KEY_RELEASE;
-                        // Suppress key repeats.
-                        if ((flags & KEY_REPEAT) == 0)
-                        {
-                            keyEventInternal(evt, getKey(value));
-                            if (evt == gameplay::Keyboard::KEY_PRESS && (flags & KEY_SYM_VALID))
-                            {
-                                int unicode = getUnicode(value);
-                                if (unicode)
-                                    keyEventInternal(gameplay::Keyboard::KEY_CHAR, unicode);
-                            }
-                        }
-                        break;
-                    }
-#ifdef USE_BLACKBERRY_GAMEPAD
-                    case SCREEN_EVENT_DEVICE:
-                    {
-                        // A device was attached or removed.
-                        screen_device_t device;
-                        int attached;
-
-                        screen_get_event_property_pv(__screenEvent, SCREEN_PROPERTY_DEVICE, (void**)&device);
-                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_ATTACHED, &attached);
-
-                        if (attached)
-                        {
-                            int type;
-                            screen_get_device_property_iv(device, SCREEN_PROPERTY_TYPE, &type);
-                            if (type == SCREEN_EVENT_GAMEPAD || type == SCREEN_EVENT_JOYSTICK)
-                            {
-                                int buttonCount = 0;
-                                int joystickCount = 0;
-                                int productId;
-                                int vendorId;
-                                char productString[64];
-                                char vendorString[64];
-                                queryGamepad(device, &buttonCount, &joystickCount, &productId, &vendorId, productString, vendorString);
-                                Platform::gamepadEventConnectedInternal(device, buttonCount, joystickCount, 0, vendorId, productId, vendorString, productString);
-                            }
-                        }
-                        else
-                        {
-                            Platform::gamepadEventDisconnectedInternal(device);
-                        }
-
-                        break;
-                    }
-#endif
-                    default:
-                        break;
-                }
-            }
-            else if (domain == navigator_get_domain())
-            {
-                switch (bps_event_get_code(event))
-                {
-                case NAVIGATOR_SWIPE_DOWN:
-                    _game->menuEvent();
-                    break;
-                case NAVIGATOR_WINDOW_STATE:
-                {
-                    navigator_window_state_t state = navigator_event_get_window_state(event);
-                    switch (state)
-                    {
-                    case NAVIGATOR_WINDOW_FULLSCREEN:
-                        if (!__screenFullscreen)
-                            __screenFullscreen = true;
-                        _game->resume();
-                        suspended = false;
-                        break;
-                    case NAVIGATOR_WINDOW_THUMBNAIL:
-                    case NAVIGATOR_WINDOW_INVISIBLE:
-                        if (__screenFullscreen && !suspended)
-                        {
-                            _game->pause();
-                            suspended = true;
-                        }
-                        break;
-                    }
-                    break;
-                }
-                case NAVIGATOR_EXIT:
-                	// Call Game::shutdown directly, instead of Game::exit.
-                	// We need to do this since exit() queues a request to shutdown for the
-                	// next frame, which will never get executed because we are suspended.
-                    _game->shutdown();
-                    break;
-                }
-            }
-            else if (domain == sensor_get_domain())
-            {
-                if (bps_event_get_code(event) == SENSOR_AZIMUTH_PITCH_ROLL_READING)
-                {
-                    float azimuth;
-                    sensor_event_get_apr(event, &azimuth, &__pitch, &__roll);
-                }
-                else if (bps_event_get_code(event) == SENSOR_ACCELEROMETER_READING)
-                {
-                    sensor_event_get_xyz(event, &__accelRawX, &__accelRawY, &__accelRawZ);
-                }
-                else if (bps_event_get_code(event) == SENSOR_GYROSCOPE_READING)
-                {
-                    sensor_event_get_xyz(event, &__gyroRawX, &__gyroRawY, &__gyroRawZ);
-                }
-            }
-        }
-
-        // If we are done, then exit.
-        if (_game->getState() == Game::UNINITIALIZED)
-            break;
-
-        if (!suspended)
-        {
-            _game->frame();
-
-            // Post the new frame to the display.
-            // Note that there are a couple cases where eglSwapBuffers could fail
-            // with an error code that requires a certain level of re-initialization:
-            //
-            // 1) EGL_BAD_NATIVE_WINDOW - Called when the surface we're currently using
-            //    is invalidated. This would require us to destroy our EGL surface,
-            //    close our OpenKODE window, and start again.
-            //
-            // 2) EGL_CONTEXT_LOST - Power management event that led to our EGL context
-            //    being lost. Requires us to re-create and re-initalize our EGL context
-            //    and all OpenGL ES state.
-            //
-            // For now, if we get these, we'll simply exit.
-            rc = eglSwapBuffers(__eglDisplay, __eglSurface);
-            if (rc != EGL_TRUE)
-            {
-                _game->shutdown();
-                perror("eglSwapBuffers");
-                break;
-            }
-        }
-    }
-
-    screen_stop_events(__screenContext);
-    bps_shutdown();
-    screen_destroy_context(__screenContext);
-
-    return 0;
-}
-    
-void Platform::signalShutdown() 
-{
-    // nothing to do  
-}
-
-bool Platform::canExit()
-{
-    return true;
-}
-
-unsigned int Platform::getDisplayWidth()
-{
-    return __screenWindowSize[0];
-}
-
-unsigned int Platform::getDisplayHeight()
-{
-    return __screenWindowSize[1];
-}
-
-double Platform::getAbsoluteTime()
-{
-    clock_gettime(CLOCK_REALTIME, &__timespec);
-    double now = timespec2millis(&__timespec);
-    __timeAbsolute = now - __timeStart;
-
-    return __timeAbsolute;
-}
-
-void Platform::setAbsoluteTime(double time)
-{
-    __timeAbsolute = time;
-}
-
-bool Platform::isVsync()
-{
-    return __vsync;
-}
-
-void Platform::setVsync(bool enable)
-{
-    eglSwapInterval(__eglDisplay, enable ? 1 : 0);
-    __vsync = enable;
-}
-
-void Platform::swapBuffers()
-{
-    if (__eglDisplay && __eglSurface)
-        eglSwapBuffers(__eglDisplay, __eglSurface);
-}
-
-void Platform::sleep(long ms)
-{
-    usleep(ms * 1000);
-}
-
-void Platform::setMultiSampling(bool enabled)
-{
-    if (enabled == __multiSampling)
-    {
-        return;
-    }
-
-    //todo
-
-    __multiSampling = enabled;
-}
-
-bool Platform::isMultiSampling()
-{
-    return __multiSampling;
-}
-
-void Platform::setMultiTouch(bool enabled)
-{
-    __multiTouch = enabled;
-}
-
-bool Platform::isMultiTouch()
-{
-    return __multiTouch;
-}
-
-bool Platform::hasAccelerometer()
-{
-    return true;
-}
-
-void Platform::getAccelerometerValues(float* pitch, float* roll)
-{
-    GP_ASSERT(pitch);
-    GP_ASSERT(roll);
-
-    switch(__orientationAngle)
-    {
-    // Landscape based device adjusting for landscape game mode
-    case 0:
-        if (pitch)
-            *pitch = __pitch;
-        if (roll)
-            *roll = -__roll;
-        break;
-    case 180:
-        if (pitch)
-            *pitch = -__pitch;
-        if (roll)
-            *roll = __roll;
-        break;
-
-    // Portrait based device adjusting for landscape game mode
-    case 90:
-        if (pitch)
-            *pitch = -__roll;
-        if (roll)
-            *roll = -__pitch;
-        break;
-
-    case  270:
-        if (pitch)
-            *pitch = __roll;
-        if (roll)
-            *roll = __pitch;
-        break;
-
-    default:
-        break;
-    }
-}
-
-void Platform::getRawSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
-{
-	if (accelX)
-	{
-		*accelX = __accelRawX;
-	}
-
-	if (accelY)
-	{
-		*accelY = __accelRawY;
-	}
-
-	if (accelZ)
-	{
-		*accelZ = __accelRawZ;
-	}
-
-	if (gyroX)
-	{
-		*gyroX = __gyroRawX;
-	}
-
-	if (gyroY)
-	{
-		*gyroY = __gyroRawY;
-	}
-
-	if (gyroZ)
-	{
-		*gyroZ = __gyroRawZ;
-	}
-}
-
-void Platform::getArguments(int* argc, char*** argv)
-{
-    if (argc)
-        *argc = __argc;
-    if (argv)
-        *argv = __argv;
-}
-
-bool Platform::hasMouse()
-{
-    // not supported
-    return false;
-}
-
-void Platform::setMouseCaptured(bool captured)
-{
-    // not supported
-}
-
-bool Platform::isMouseCaptured()
-{
-    // not supported
-    return false;
-}
-
-void Platform::setCursorVisible(bool visible)
-{
-    // not supported
-}
-
-bool Platform::isCursorVisible()
-{
-    // not supported
-    return false;
-}
-
-void Platform::displayKeyboard(bool display)
-{
-    if (display)
-        virtualkeyboard_show();
-    else
-        virtualkeyboard_hide();
-}
-
-void Platform::shutdownInternal()
-{
-    Game::getInstance()->shutdown();
-}
-
-bool Platform::isGestureSupported(Gesture::GestureEvent evt)
-{
-    // All are supported no need to test the bitset
-    return true;
-}
-
-void Platform::registerGesture(Gesture::GestureEvent evt)
-{
-    switch(evt)
-    {
-    case Gesture::GESTURE_ANY_SUPPORTED:
-        __gestureEventsProcessed.set();
-        break;
-
-    case Gesture::GESTURE_SWIPE:
-    case Gesture::GESTURE_PINCH:
-    case Gesture::GESTURE_TAP:
-        __gestureEventsProcessed.set(evt);
-        break;
-
-    default:
-        break;
-    }
-}
-
-void Platform::unregisterGesture(Gesture::GestureEvent evt)
-{
-    switch(evt)
-    {
-    case Gesture::GESTURE_ANY_SUPPORTED:
-        __gestureEventsProcessed.reset();
-        break;
-
-    case Gesture::GESTURE_SWIPE:
-    case Gesture::GESTURE_PINCH:
-    case Gesture::GESTURE_TAP:
-        __gestureEventsProcessed.set(evt, 0);
-        break;
-
-    default:
-        break;
-    }
-}
-    
-bool Platform::isGestureRegistered(Gesture::GestureEvent evt)
-{
-    return __gestureEventsProcessed.test(evt);
-}
-
-bool Platform::launchURL(const char* url)
-{
-    if (url == NULL || *url == '\0')
-        return false;
-
-    return navigator_invoke(url, NULL) == BPS_SUCCESS;
-}
-
-}
-
-#endif
+        }
+
+    case GESTURE_TAP:
+        {
+            if ( __gestureEventsProcessed.test(Gesture::GESTURE_TAP) )
+            {
+                gesture_tap_t* tap = (gesture_tap_t*)gesture;
+                Platform::gestureTapEventInternal(tap->touch_coords.x, tap->touch_coords.y);
+            }
+            break;
+        }
+
+    default:
+        break;
+
+    }
+}
+
+#ifdef GP_USE_GAMEPAD
+
+static const char* __vendorStrings[] =
+{
+    "SteelSeries",
+    "Nintendo",
+};
+
+static const char* __productStrings[] =
+{
+    "FREE",
+    "Wii Remote",
+};
+
+static const int __VIDs[] = {
+    0x1038,
+    0x057e,
+};
+
+static const int __PIDs[] = {
+    0x1412,
+    0x0306,
+};
+
+static const unsigned int __knownGamepads = 2;
+
+void queryGamepad(GamepadHandle handle, int* buttonCount, int* joystickCount, int* productId, int* vendorId, char* productString, char* vendorString)
+{
+    char id[128];
+    screen_get_device_property_iv(handle, SCREEN_PROPERTY_BUTTON_COUNT, buttonCount);
+    screen_get_device_property_cv(handle, SCREEN_PROPERTY_ID_STRING, 128, id);
+    screen_get_device_property_cv(handle, SCREEN_PROPERTY_PRODUCT, 64, productString);
+    screen_get_device_property_cv(handle, SCREEN_PROPERTY_VENDOR, 64, vendorString);
+
+    // Check for the existence of analog sticks.
+    int analogs[3];
+    if (!screen_get_device_property_iv(handle, SCREEN_PROPERTY_ANALOG0, analogs))
+    {
+    	++(*joystickCount);
+    }
+
+    if (!screen_get_device_property_iv(handle, SCREEN_PROPERTY_ANALOG1, analogs))
+    {
+    	++(*joystickCount);
+    }
+
+    // ID string format: A-BBBB-CCCC-D.D
+    // A is the device's index
+    // BBBB is the device's Vendor ID (in hexadecimal)
+    // CCCC is the device's Product ID (also in hexadecimal)
+    // D.D is the device's version number
+    char* token = strtok(id, "-");
+    token = strtok(NULL, "-");
+    if (token)
+    {
+	    *vendorId = strtol(token, NULL, 16);
+    }
+
+    token = strtok(NULL, "-");
+    if (token)
+    {
+        *productId = strtol(token, NULL, 16);
+    }
+
+    // For gamepads unknown to BB10,
+    // check VID and PID against gamepads known to gameplay.
+    if (strlen(productString) == 0 || strlen(vendorString) == 0)
+    {
+        for (unsigned int i = 0; i < __knownGamepads; ++i)
+        {
+            if (__VIDs[i] == *vendorId && __PIDs[i] == *productId)
+            {
+            	strcpy(vendorString, __vendorStrings[i]);
+                strcpy(productString, __productStrings[i]);
+            }
+        }
+    }
+}
+
+void Platform::pollGamepadState(Gamepad* gamepad)
+{
+	unsigned int buttons;
+    screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_BUTTONS, (int*)&buttons);
+	gamepad->setButtons(buttons);
+
+    unsigned int i;
+    for (i = 0; i < gamepad->_joystickCount; ++i)
+    {
+        GP_ASSERT(i < 2);
+
+        int analog[3];
+        switch (i)
+        {
+        case 0:
+            screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_ANALOG0, analog);
+            break;
+        case 1:
+            screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_ANALOG1, analog);
+            break;
+        }
+        
+        // So far we've tested two gamepads with analog sticks on BlackBerry:
+        // the SteelSeries FREE, and the iControlPad.
+        // Both return values between -128 and +127, with the y axis starting from
+        // the top at -128.
+        // 1 / 128 == 0.0078125f
+        // 1 / 127 == 0.0078740157480315f
+        float x = (float)analog[0];
+        float y = -(float)analog[1];
+        x *= (x < 0) ? 0.0078125f : 0.0078740157480315f;
+        y *= (y > 0) ? 0.0078125f : 0.0078740157480315f;
+
+		gamepad->setJoystickValue(i, x, y);
+    }
+
+    for (i = 0; i < gamepad->_triggerCount; ++i)
+    {
+        GP_ASSERT(i < 2);
+
+        int analog[3];
+        switch (i)
+        {
+        case 0:
+            screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_ANALOG0, analog);
+            break;
+        case 1:
+            screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_ANALOG1, analog);
+            break;
+        }
+
+        float value = (float)analog[2] * 0.0078125f;
+		gamepad->setTriggerValue(i, value);
+    }
+}
+#else
+void Platform::pollGamepadState(Gamepad* gamepad)
+{
+}
+#endif
+
+Platform::Platform(Game* game)
+    : _game(game)
+{
+}
+
+Platform::~Platform()
+{
+    if (__eglDisplay != EGL_NO_DISPLAY)
+    {
+        eglMakeCurrent(__eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    }
+
+    if (__eglSurface != EGL_NO_SURFACE)
+    {
+        eglDestroySurface(__eglDisplay, __eglSurface);
+        __eglSurface = EGL_NO_SURFACE;
+    }
+
+    if (__eglContext != EGL_NO_CONTEXT)
+    {
+        eglDestroyContext(__eglDisplay, __eglContext);
+        __eglContext = EGL_NO_CONTEXT;
+    }
+
+    if (__eglDisplay != EGL_NO_DISPLAY)
+    {
+        eglTerminate(__eglDisplay);
+        __eglDisplay = EGL_NO_DISPLAY;
+    }
+
+    if (__screenWindow)
+    {
+        screen_destroy_window(__screenWindow);
+        __screenWindow = NULL;
+    }
+
+    if (__screenEvent)
+    {
+        screen_destroy_event(__screenEvent);
+        __screenEvent = NULL;
+    }
+
+    if (__screenContext)
+    {
+        screen_destroy_context(__screenContext);
+        __screenContext = NULL;
+    }
+}
+
+Platform* Platform::create(Game* game, void* attachToWindow)
+{
+    FileSystem::setResourcePath("./app/native/");
+    Platform* platform = new Platform(game);
+
+    // Query game config
+    int samples = 0;
+    Properties* config = Game::getInstance()->getConfig()->getNamespace("window", true);
+    if (config)
+    {
+        samples = std::max(config->getInt("samples"), 0);
+    }
+
+    __gestureSet = gestures_set_alloc();
+    swipe_gesture_alloc(NULL, gesture_callback, __gestureSet);
+    pinch_gesture_alloc(NULL, gesture_callback, __gestureSet);
+    tap_gesture_alloc(NULL, gesture_callback, __gestureSet);
+
+    bps_initialize();
+
+    // Initialize navigator and orientation
+    static const int SENSOR_RATE = 25000; // (25000 microseconds = 40 Hz)
+    sensor_set_rate(SENSOR_TYPE_AZIMUTH_PITCH_ROLL, SENSOR_RATE);
+    sensor_set_rate(SENSOR_TYPE_ACCELEROMETER, SENSOR_RATE);
+    sensor_set_rate(SENSOR_TYPE_GYROSCOPE, SENSOR_RATE);
+    sensor_set_skip_duplicates(SENSOR_TYPE_AZIMUTH_PITCH_ROLL, true);
+    sensor_set_skip_duplicates(SENSOR_TYPE_ACCELEROMETER, true);
+    sensor_set_skip_duplicates(SENSOR_TYPE_GYROSCOPE, true);
+    sensor_request_events(SENSOR_TYPE_AZIMUTH_PITCH_ROLL);
+    sensor_request_events(SENSOR_TYPE_ACCELEROMETER);
+    sensor_request_events(SENSOR_TYPE_GYROSCOPE);
+    navigator_request_events(0);
+    navigator_rotation_lock(true);
+    __orientationAngle = atoi(getenv("ORIENTATION"));
+
+    int rc = 0;
+    int screenFormat = SCREEN_FORMAT_RGBA8888;
+#ifdef __X86__
+    int screenUsage = SCREEN_USAGE_OPENGL_ES2;
+#else
+    int screenUsage = SCREEN_USAGE_DISPLAY|SCREEN_USAGE_OPENGL_ES2; // Physical device copy directly into physical display
+#endif
+    int screenSwapInterval = WINDOW_VSYNC ? 1 : 0;
+    int screenTransparency = SCREEN_TRANSPARENCY_NONE;
+
+    char *width_str = getenv("WIDTH");
+    char *height_str = getenv("HEIGHT");
+
+    // Hard-coded to (0,0).
+    int windowPosition[] =
+    {
+        0, 0
+    };
+
+    EGLint eglConfigCount;
+
+    // Hard-coded to 32-bit/OpenGL ES 2.0.
+    // NOTE: EGL_SAMPLE_BUFFERS and EGL_SAMPLES MUST remain at the beginning of the attribute list
+    // since they are expected to be at indices 0-3 in config fallback code later.
+    EGLint eglConfigAttrs[] =
+    {
+        EGL_SAMPLE_BUFFERS,     samples > 0 ? 1 : 0,
+        EGL_SAMPLES,            samples,
+        EGL_RED_SIZE,           8,
+        EGL_GREEN_SIZE,         8,
+        EGL_BLUE_SIZE,          8,
+        EGL_ALPHA_SIZE,         8,
+        EGL_DEPTH_SIZE,         24,
+        EGL_STENCIL_SIZE,       8,
+        EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
+        EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
+        EGL_NONE
+    };
+    __multiSampling = samples > 0;
+
+    const EGLint eglContextAttrs[] =
+    {
+        EGL_CONTEXT_CLIENT_VERSION,    2,
+        EGL_NONE
+    };
+
+    const EGLint eglSurfaceAttrs[] =
+    {
+        EGL_RENDER_BUFFER,    EGL_BACK_BUFFER,
+        EGL_NONE
+    };
+
+    // Create the screen context.
+    rc = screen_create_context(&__screenContext, 0);
+    if (rc)
+    {
+        perror("screen_create_context");
+        goto error;
+    }
+
+    // Create the screen window.
+    rc = screen_create_window(&__screenWindow, __screenContext);
+    if (rc)
+    {
+        perror("screen_create_window");
+        goto error;
+    }
+
+    // Set/get any window properties.
+    rc = screen_set_window_property_iv(__screenWindow, SCREEN_PROPERTY_FORMAT, &screenFormat);
+    if (rc)
+    {
+        perror("screen_set_window_property_iv(SCREEN_PROPERTY_FORMAT)");
+        goto error;
+    }
+
+    rc = screen_set_window_property_iv(__screenWindow, SCREEN_PROPERTY_USAGE, &screenUsage);
+    if (rc)
+    {
+        perror("screen_set_window_property_iv(SCREEN_PROPERTY_USAGE)");
+        goto error;
+    }
+
+    if (width_str && height_str)
+    {
+        __screenWindowSize[0] = atoi(width_str);
+        __screenWindowSize[1] = atoi(height_str);
+    }
+    else
+    {
+        screen_display_t screen_display;
+        rc = screen_get_window_property_pv(__screenWindow, SCREEN_PROPERTY_DISPLAY, (void **)&screen_display);
+        if (rc)
+        {
+            perror("screen_get_window_property_pv(SCREEN_PROPERTY_DISPLAY)");
+            goto error;
+        }
+
+        screen_display_mode_t screen_mode;
+        rc = screen_get_display_property_pv(screen_display, SCREEN_PROPERTY_MODE, (void**)&screen_mode);
+        if (rc)
+        {
+            perror("screen_get_display_property_pv(SCREEN_PROPERTY_MODE)");
+            goto error;
+        }
+
+        int size[2];
+        rc = screen_get_window_property_iv(__screenWindow, SCREEN_PROPERTY_BUFFER_SIZE, size);
+        if (rc)
+        {
+            perror("screen_get_window_property_iv(SCREEN_PROPERTY_BUFFER_SIZE)");
+            goto error;
+        }
+
+        __screenWindowSize[0] = size[0];
+        __screenWindowSize[1] = size[1];
+
+        if ((__orientationAngle == 0) || (__orientationAngle == 180))
+        {
+            if (((screen_mode.width > screen_mode.height) && (size[0] < size[1])) ||
+                ((screen_mode.width < screen_mode.height) && (size[0] > size[1])))
+            {
+                __screenWindowSize[1] = size[0];
+                __screenWindowSize[0] = size[1];
+            }
+        }
+        else if ((__orientationAngle == 90) || (__orientationAngle == 270))
+        {
+            if (((screen_mode.width > screen_mode.height) && (size[0] > size[1])) ||
+                ((screen_mode.width < screen_mode.height) && (size[0] < size[1])))
+            {
+                __screenWindowSize[1] = size[0];
+                __screenWindowSize[0] = size[1];
+            }
+        }
+        else
+        {
+            perror("Navigator returned an unexpected orientation angle.");
+            goto error;
+        }
+
+
+        rc = screen_set_window_property_iv(__screenWindow, SCREEN_PROPERTY_ROTATION, &__orientationAngle);
+        if (rc)
+        {
+            perror("screen_set_window_property_iv(SCREEN_PROPERTY_ROTATION)");
+            goto error;
+        }
+    }
+
+    rc = screen_set_window_property_iv(__screenWindow, SCREEN_PROPERTY_BUFFER_SIZE, __screenWindowSize);
+    if (rc)
+    {
+        perror("screen_set_window_property_iv(SCREEN_PROPERTY_BUFFER_SIZE)");
+        goto error;
+    }
+
+    if (windowPosition[0] != 0 || windowPosition[1] != 0)
+    {
+        rc = screen_set_window_property_iv(__screenWindow, SCREEN_PROPERTY_POSITION, windowPosition);
+        if (rc)
+        {
+            perror("screen_set_window_property_iv(SCREEN_PROPERTY_POSITION)");
+            goto error;
+        }
+    }
+
+    rc = screen_set_window_property_iv(__screenWindow, SCREEN_PROPERTY_TRANSPARENCY, &screenTransparency);
+    if (rc)
+    {
+        perror("screen_set_window_property_iv(SCREEN_PROPERTY_TRANSPARENCY)");
+        goto error;
+    }
+
+    // Double buffered.
+    rc = screen_create_window_buffers(__screenWindow, 2);
+    if (rc)
+    {
+        perror("screen_create_window_buffers");
+        goto error;
+    }
+
+    // Create screen event object.
+    rc = screen_create_event(&__screenEvent);
+    if (rc)
+    {
+        perror("screen_create_event");
+        goto error;
+    }
+
+    // Request screen events.
+    screen_request_events(__screenContext);
+
+    // Get the EGL display and initialize.
+    __eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    if (__eglDisplay == EGL_NO_DISPLAY)
+    {
+        perror("eglGetDisplay");
+        goto error;
+    }
+    if (eglInitialize(__eglDisplay, NULL, NULL) != EGL_TRUE)
+    {
+        perror("eglInitialize");
+        goto error;
+    }
+
+    if (eglChooseConfig(__eglDisplay, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) != EGL_TRUE || eglConfigCount == 0)
+    {
+        bool success = false;
+        while (samples)
+        {
+            // Try lowering the MSAA sample count until we find a supported config
+            GP_WARN("Failed to find a valid EGL configuration with EGL samples=%d. Trying samples=%d instead.", samples, samples/2);
+            samples /= 2;
+            eglConfigAttrs[1] = samples > 0 ? 1 : 0;
+            eglConfigAttrs[3] = samples;
+            if (eglChooseConfig(__eglDisplay, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) == EGL_TRUE && eglConfigCount > 0)
+            {
+                success = true;
+                break;
+            }
+        }
+
+        __multiSampling = samples > 0;
+
+        if (!success)
+        {
+            checkErrorEGL("eglChooseConfig");
+            goto error;
+        }
+    }
+
+    __eglContext = eglCreateContext(__eglDisplay, __eglConfig, EGL_NO_CONTEXT, eglContextAttrs);
+    if (__eglContext == EGL_NO_CONTEXT)
+    {
+        checkErrorEGL("eglCreateContext");
+        goto error;
+    }
+
+    __eglSurface = eglCreateWindowSurface(__eglDisplay, __eglConfig, __screenWindow, eglSurfaceAttrs);
+    if (__eglSurface == EGL_NO_SURFACE)
+    {
+        checkErrorEGL("eglCreateWindowSurface");
+        goto error;
+    }
+
+    if (eglMakeCurrent(__eglDisplay, __eglSurface, __eglSurface, __eglContext) != EGL_TRUE)
+    {
+        checkErrorEGL("eglMakeCurrent");
+        goto error;
+    }
+
+    // Set vsync.
+    eglSwapInterval(__eglDisplay, screenSwapInterval);
+
+    // Initialize OpenGL ES extensions.
+    __glExtensions = (const char*)glGetString(GL_EXTENSIONS);
+
+    if (strstr(__glExtensions, "GL_OES_vertex_array_object") || strstr(__glExtensions, "GL_ARB_vertex_array_object"))
+    {
+        glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES");
+        glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES");
+        glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES");
+        glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES");
+    }
+
+ #ifdef GP_USE_GAMEPAD
+
+    screen_device_t* screenDevs;
+
+    // Discover initial gamepad devices.
+    int count;
+    screen_get_context_property_iv(__screenContext, SCREEN_PROPERTY_DEVICE_COUNT, &count);
+    screenDevs = (screen_device_t*)calloc(count, sizeof(screen_device_t));
+    screen_get_context_property_pv(__screenContext, SCREEN_PROPERTY_DEVICES, (void**)screenDevs);
+
+	for (int i = 0; i < count; i++) 
+    {
+	    int type;
+        screen_get_device_property_iv(screenDevs[i], SCREEN_PROPERTY_TYPE, &type);
+
+        if (type == SCREEN_EVENT_GAMEPAD || type == SCREEN_EVENT_JOYSTICK)
+        {
+            int buttonCount = 0;
+            int joystickCount = 0;
+            int productId;
+            int vendorId;
+            char productString[64];
+            char vendorString[64];
+            queryGamepad(screenDevs[i], &buttonCount, &joystickCount, &productId, &vendorId, productString, vendorString);
+            Platform::gamepadEventConnectedInternal(screenDevs[i], buttonCount, joystickCount, 0, vendorId, productId, vendorString, productString);
+        }
+	}
+	free(screenDevs);
+#endif
+
+    return platform;
+
+error:
+
+    return NULL;
+}
+
+/**
+ * Convert the timespec into milliseconds.
+ */
+double timespec2millis(struct timespec *a)
+{
+    GP_ASSERT(a);
+    return (1000.0 * a->tv_sec) + (0.000001 * a->tv_nsec);
+}
+
+/**
+ * Fires a mouse event or a touch event on the game.
+ * If the mouse event is not consumed, a touch event is fired instead.
+ *
+ * @param mouseEvent The mouse event to fire.
+ * @param touchEvent The touch event to fire.
+ * @param x The x position of the touch in pixels.
+ * @param y The y position of the touch in pixels.
+ */
+void mouseOrTouchEvent(Mouse::MouseEvent mouseEvent, Touch::TouchEvent touchEvent, int x, int y)
+{
+    if (!gameplay::Platform::mouseEventInternal(mouseEvent, x, y, 0))
+    {
+        Platform::touchEventInternal(touchEvent, x, y, 0, true);
+    }
+}
+
+int Platform::enterMessagePump()
+{
+    GP_ASSERT(_game);
+
+    int rc;
+    int eventType;
+    int flags;
+    int value;
+    int position[2];
+    int domain;
+    mtouch_event_t touchEvent;
+    bool suspended = false;
+
+    // Get the initial time.
+    clock_gettime(CLOCK_REALTIME, &__timespec);
+    __timeStart = timespec2millis(&__timespec);
+    __timeAbsolute = 0L;
+
+    _game->run();
+
+    // Message loop.
+    while (true)
+    {
+        bps_event_t* event = NULL;
+        
+        while (true)
+        {
+            rc = bps_get_event(&event, 1);
+            GP_ASSERT(rc == BPS_SUCCESS);
+
+            if (event == NULL)
+                break;
+
+            domain = bps_event_get_domain(event);
+
+            if (domain == screen_get_domain())
+            {
+                __screenEvent = screen_event_get_event(event);
+                screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_TYPE, &eventType);
+                switch (eventType)
+                {
+                    case SCREEN_EVENT_MTOUCH_TOUCH:
+                    {
+                        screen_get_mtouch_event(__screenEvent, &touchEvent, 0);
+                        if (__gestureEventsProcessed.any())
+                            rc = gestures_set_process_event(__gestureSet, &touchEvent, NULL);
+
+                        if ( !rc && (__multiTouch || touchEvent.contact_id == 0) )
+                        {
+                            gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, touchEvent.x, touchEvent.y, touchEvent.contact_id);
+                        }
+                        break;
+                    }
+
+                    case SCREEN_EVENT_MTOUCH_RELEASE:
+                    {
+                        screen_get_mtouch_event(__screenEvent, &touchEvent, 0);
+                        if (__gestureEventsProcessed.any())
+                            rc = gestures_set_process_event(__gestureSet, &touchEvent, NULL);
+
+                        if ( !rc && (__multiTouch || touchEvent.contact_id == 0) )
+                        {
+                            gameplay::Platform::touchEventInternal(Touch::TOUCH_RELEASE, touchEvent.x, touchEvent.y, touchEvent.contact_id);
+                        }
+                        if (__gestureSwipeRecognized)
+                        {
+                            __gestureSwipeRecognized = false;
+                        }
+                        break;
+                    }
+
+                    case SCREEN_EVENT_MTOUCH_MOVE:
+                    {
+                        screen_get_mtouch_event(__screenEvent, &touchEvent, 0);
+                        if (__gestureEventsProcessed.any())
+                            rc = gestures_set_process_event(__gestureSet, &touchEvent, NULL);
+
+                        if ( !rc && (__multiTouch || touchEvent.contact_id == 0) )
+                        {
+                            gameplay::Platform::touchEventInternal(Touch::TOUCH_MOVE, touchEvent.x, touchEvent.y, touchEvent.contact_id);
+                        }
+                        break;
+                    }
+
+                    case SCREEN_EVENT_POINTER:
+                    {
+                        static int mouse_pressed = 0;
+                        int buttons;
+                        int wheel;
+                        // A move event will be fired unless a button state changed.
+                        bool move = true;
+                        bool left_move = false;
+                        // This is a mouse move event, it is applicable to a device with a usb mouse or simulator.
+                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_BUTTONS, &buttons);
+                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_SOURCE_POSITION, position);
+                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel);
+
+                        // Handle left mouse. Interpret as touch if the left mouse event is not consumed.
+                        if (buttons & SCREEN_LEFT_MOUSE_BUTTON)
+                        {
+                            if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON)
+                            {
+                                left_move = true;
+                            }
+                            else
+                            {
+                                move = false;
+                                mouse_pressed |= SCREEN_LEFT_MOUSE_BUTTON;
+                                mouseOrTouchEvent(Mouse::MOUSE_PRESS_LEFT_BUTTON, Touch::TOUCH_PRESS, position[0], position[1]);
+                            }
+                        }
+                        else if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON)
+                        {
+                            move = false;
+                            mouse_pressed &= ~SCREEN_LEFT_MOUSE_BUTTON;
+                            mouseOrTouchEvent(Mouse::MOUSE_RELEASE_LEFT_BUTTON, Touch::TOUCH_RELEASE, position[0], position[1]);
+                        }
+
+                        // Handle right mouse.
+                        if (buttons & SCREEN_RIGHT_MOUSE_BUTTON)
+                        {
+                            if ((mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON) == 0)
+                            {
+                                move = false;
+                                mouse_pressed |= SCREEN_RIGHT_MOUSE_BUTTON;
+                                gameplay::Platform::mouseEventInternal(Mouse::MOUSE_PRESS_RIGHT_BUTTON, position[0], position[1], 0);
+                            }
+                        }
+                        else if (mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON)
+                        {
+                            move = false;
+                            mouse_pressed &= ~SCREEN_RIGHT_MOUSE_BUTTON;
+                            gameplay::Platform::mouseEventInternal(Mouse::MOUSE_RELEASE_RIGHT_BUTTON, position[0], position[1], 0);
+                        }
+
+                        // Handle middle mouse.
+                        if (buttons & SCREEN_MIDDLE_MOUSE_BUTTON)
+                        {
+                            if ((mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON) == 0)
+                            {
+                                move = false;
+                                mouse_pressed |= SCREEN_MIDDLE_MOUSE_BUTTON;
+                                gameplay::Platform::mouseEventInternal(Mouse::MOUSE_PRESS_MIDDLE_BUTTON, position[0], position[1], 0);
+                            }
+                        }
+                        else if (mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON)
+                        {
+                            move = false;
+                            mouse_pressed &= ~SCREEN_MIDDLE_MOUSE_BUTTON;
+                            gameplay::Platform::mouseEventInternal(Mouse::MOUSE_RELEASE_MIDDLE_BUTTON, position[0], position[1], 0);
+                        }
+
+                        // Fire a move event if none of the buttons changed.
+                        if (left_move)
+                        {
+                            mouseOrTouchEvent(Mouse::MOUSE_MOVE, Touch::TOUCH_MOVE, position[0], position[1]);
+                        }
+                        else if (move)
+                        {
+                            gameplay::Platform::mouseEventInternal(Mouse::MOUSE_MOVE, position[0], position[1], 0);
+                        }
+
+                        // Handle mouse wheel events.
+                        if (wheel)
+                        {
+                            gameplay::Platform::mouseEventInternal(Mouse::MOUSE_WHEEL, position[0], position[1], -wheel);
+                        }
+                        break;
+                    }
+
+                    case SCREEN_EVENT_KEYBOARD:
+                    {
+                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_KEY_FLAGS, &flags);
+                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_KEY_SYM, &value);
+                        gameplay::Keyboard::KeyEvent evt = (flags & KEY_DOWN) ? gameplay::Keyboard::KEY_PRESS :  gameplay::Keyboard::KEY_RELEASE;
+                        // Suppress key repeats.
+                        if ((flags & KEY_REPEAT) == 0)
+                        {
+                            keyEventInternal(evt, getKey(value));
+                            if (evt == gameplay::Keyboard::KEY_PRESS && (flags & KEY_SYM_VALID))
+                            {
+                                int unicode = getUnicode(value);
+                                if (unicode)
+                                    keyEventInternal(gameplay::Keyboard::KEY_CHAR, unicode);
+                            }
+                        }
+                        break;
+                    }
+#ifdef GP_USE_GAMEPAD
+                    case SCREEN_EVENT_DEVICE:
+                    {
+                        // A device was attached or removed.
+                        screen_device_t device;
+                        int attached;
+
+                        screen_get_event_property_pv(__screenEvent, SCREEN_PROPERTY_DEVICE, (void**)&device);
+                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_ATTACHED, &attached);
+
+                        if (attached)
+                        {
+                            int type;
+                            screen_get_device_property_iv(device, SCREEN_PROPERTY_TYPE, &type);
+                            if (type == SCREEN_EVENT_GAMEPAD || type == SCREEN_EVENT_JOYSTICK)
+                            {
+                                int buttonCount = 0;
+                                int joystickCount = 0;
+                                int productId;
+                                int vendorId;
+                                char productString[64];
+                                char vendorString[64];
+                                queryGamepad(device, &buttonCount, &joystickCount, &productId, &vendorId, productString, vendorString);
+                                Platform::gamepadEventConnectedInternal(device, buttonCount, joystickCount, 0, vendorId, productId, vendorString, productString);
+                            }
+                        }
+                        else
+                        {
+                            Platform::gamepadEventDisconnectedInternal(device);
+                        }
+
+                        break;
+                    }
+#endif
+                    default:
+                        break;
+                }
+            }
+            else if (domain == navigator_get_domain())
+            {
+                switch (bps_event_get_code(event))
+                {
+                case NAVIGATOR_WINDOW_STATE:
+                {
+                    navigator_window_state_t state = navigator_event_get_window_state(event);
+                    switch (state)
+                    {
+                    case NAVIGATOR_WINDOW_FULLSCREEN:
+                        if (!__screenFullscreen)
+                            __screenFullscreen = true;
+                        _game->resume();
+                        suspended = false;
+                        break;
+                    case NAVIGATOR_WINDOW_THUMBNAIL:
+                    case NAVIGATOR_WINDOW_INVISIBLE:
+                        if (__screenFullscreen && !suspended)
+                        {
+                            _game->pause();
+                            suspended = true;
+                        }
+                        break;
+                    }
+                    break;
+                }
+                case NAVIGATOR_EXIT:
+                	// Call Game::shutdown directly, instead of Game::exit.
+                	// We need to do this since exit() queues a request to shutdown for the
+                	// next frame, which will never get executed because we are suspended.
+                    _game->shutdown();
+                    break;
+                }
+            }
+            else if (domain == sensor_get_domain())
+            {
+                if (bps_event_get_code(event) == SENSOR_AZIMUTH_PITCH_ROLL_READING)
+                {
+                    float azimuth;
+                    sensor_event_get_apr(event, &azimuth, &__pitch, &__roll);
+                }
+                else if (bps_event_get_code(event) == SENSOR_ACCELEROMETER_READING)
+                {
+                    sensor_event_get_xyz(event, &__accelRawX, &__accelRawY, &__accelRawZ);
+                }
+                else if (bps_event_get_code(event) == SENSOR_GYROSCOPE_READING)
+                {
+                    sensor_event_get_xyz(event, &__gyroRawX, &__gyroRawY, &__gyroRawZ);
+                }
+            }
+        }
+
+        // If we are done, then exit.
+        if (_game->getState() == Game::UNINITIALIZED)
+            break;
+
+        if (!suspended)
+        {
+            _game->frame();
+
+            // Post the new frame to the display.
+            // Note that there are a couple cases where eglSwapBuffers could fail
+            // with an error code that requires a certain level of re-initialization:
+            //
+            // 1) EGL_BAD_NATIVE_WINDOW - Called when the surface we're currently using
+            //    is invalidated. This would require us to destroy our EGL surface,
+            //    close our OpenKODE window, and start again.
+            //
+            // 2) EGL_CONTEXT_LOST - Power management event that led to our EGL context
+            //    being lost. Requires us to re-create and re-initalize our EGL context
+            //    and all OpenGL ES state.
+            //
+            // For now, if we get these, we'll simply exit.
+            rc = eglSwapBuffers(__eglDisplay, __eglSurface);
+            if (rc != EGL_TRUE)
+            {
+                _game->shutdown();
+                perror("eglSwapBuffers");
+                break;
+            }
+        }
+    }
+
+    screen_stop_events(__screenContext);
+    bps_shutdown();
+    screen_destroy_context(__screenContext);
+
+    return 0;
+}
+    
+void Platform::signalShutdown() 
+{
+    // nothing to do  
+}
+
+bool Platform::canExit()
+{
+    return true;
+}
+
+unsigned int Platform::getDisplayWidth()
+{
+    return __screenWindowSize[0];
+}
+
+unsigned int Platform::getDisplayHeight()
+{
+    return __screenWindowSize[1];
+}
+
+double Platform::getAbsoluteTime()
+{
+    clock_gettime(CLOCK_REALTIME, &__timespec);
+    double now = timespec2millis(&__timespec);
+    __timeAbsolute = now - __timeStart;
+
+    return __timeAbsolute;
+}
+
+void Platform::setAbsoluteTime(double time)
+{
+    __timeAbsolute = time;
+}
+
+bool Platform::isVsync()
+{
+    return __vsync;
+}
+
+void Platform::setVsync(bool enable)
+{
+    eglSwapInterval(__eglDisplay, enable ? 1 : 0);
+    __vsync = enable;
+}
+
+void Platform::swapBuffers()
+{
+    if (__eglDisplay && __eglSurface)
+        eglSwapBuffers(__eglDisplay, __eglSurface);
+}
+
+void Platform::sleep(long ms)
+{
+    usleep(ms * 1000);
+}
+
+void Platform::setMultiSampling(bool enabled)
+{
+    if (enabled == __multiSampling)
+    {
+        return;
+    }
+
+    // TODO:
+    __multiSampling = enabled;
+}
+
+bool Platform::isMultiSampling()
+{
+    return __multiSampling;
+}
+
+void Platform::setMultiTouch(bool enabled)
+{
+    __multiTouch = enabled;
+}
+
+bool Platform::isMultiTouch()
+{
+    return __multiTouch;
+}
+
+bool Platform::hasAccelerometer()
+{
+    return true;
+}
+
+void Platform::getAccelerometerValues(float* pitch, float* roll)
+{
+    GP_ASSERT(pitch);
+    GP_ASSERT(roll);
+
+    switch(__orientationAngle)
+    {
+    // Landscape based device adjusting for landscape game mode
+    case 0:
+        if (pitch)
+            *pitch = __pitch;
+        if (roll)
+            *roll = -__roll;
+        break;
+    case 180:
+        if (pitch)
+            *pitch = -__pitch;
+        if (roll)
+            *roll = __roll;
+        break;
+
+    // Portrait based device adjusting for landscape game mode
+    case 90:
+        if (pitch)
+            *pitch = -__roll;
+        if (roll)
+            *roll = -__pitch;
+        break;
+
+    case  270:
+        if (pitch)
+            *pitch = __roll;
+        if (roll)
+            *roll = __pitch;
+        break;
+
+    default:
+        break;
+    }
+}
+
+void Platform::getSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
+{
+	if (accelX)
+	{
+		*accelX = __accelRawX;
+	}
+
+	if (accelY)
+	{
+		*accelY = __accelRawY;
+	}
+
+	if (accelZ)
+	{
+		*accelZ = __accelRawZ;
+	}
+
+	if (gyroX)
+	{
+		*gyroX = __gyroRawX;
+	}
+
+	if (gyroY)
+	{
+		*gyroY = __gyroRawY;
+	}
+
+	if (gyroZ)
+	{
+		*gyroZ = __gyroRawZ;
+	}
+}
+
+void Platform::getArguments(int* argc, char*** argv)
+{
+    if (argc)
+        *argc = __argc;
+    if (argv)
+        *argv = __argv;
+}
+
+bool Platform::hasMouse()
+{
+    // not supported
+    return false;
+}
+
+void Platform::setMouseCaptured(bool captured)
+{
+    // not supported
+}
+
+bool Platform::isMouseCaptured()
+{
+    // not supported
+    return false;
+}
+
+void Platform::setCursorVisible(bool visible)
+{
+    // not supported
+}
+
+bool Platform::isCursorVisible()
+{
+    // not supported
+    return false;
+}
+
+void Platform::displayKeyboard(bool display)
+{
+    if (display)
+        virtualkeyboard_show();
+    else
+        virtualkeyboard_hide();
+}
+
+void Platform::shutdownInternal()
+{
+    Game::getInstance()->shutdown();
+}
+
+bool Platform::isGestureSupported(Gesture::GestureEvent evt)
+{
+    // All are supported no need to test the bitset
+    return true;
+}
+
+void Platform::registerGesture(Gesture::GestureEvent evt)
+{
+    switch(evt)
+    {
+    case Gesture::GESTURE_ANY_SUPPORTED:
+        __gestureEventsProcessed.set();
+        break;
+
+    case Gesture::GESTURE_SWIPE:
+    case Gesture::GESTURE_PINCH:
+    case Gesture::GESTURE_TAP:
+        __gestureEventsProcessed.set(evt);
+        break;
+
+    default:
+        break;
+    }
+}
+
+void Platform::unregisterGesture(Gesture::GestureEvent evt)
+{
+    switch(evt)
+    {
+    case Gesture::GESTURE_ANY_SUPPORTED:
+        __gestureEventsProcessed.reset();
+        break;
+
+    case Gesture::GESTURE_SWIPE:
+    case Gesture::GESTURE_PINCH:
+    case Gesture::GESTURE_TAP:
+        __gestureEventsProcessed.set(evt, 0);
+        break;
+
+    default:
+        break;
+    }
+}
+    
+bool Platform::isGestureRegistered(Gesture::GestureEvent evt)
+{
+    return __gestureEventsProcessed.test(evt);
+}
+
+bool Platform::launchURL(const char* url)
+{
+    if (url == NULL || *url == '\0')
+        return false;
+
+    return navigator_invoke(url, NULL) == BPS_SUCCESS;
+}
+
+}
+
+#endif

+ 1 - 1
gameplay/src/PlatformLinux.cpp

@@ -1422,7 +1422,7 @@ namespace gameplay
         *roll = 0;
     }
 
-    void Platform::getRawSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
+    void Platform::getSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
     {
         if (accelX)
         {

+ 1 - 1
gameplay/src/PlatformMacOSX.mm

@@ -1813,7 +1813,7 @@ void Platform::getAccelerometerValues(float* pitch, float* roll)
     *roll = 0;
 }
 
-void Platform::getRawSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
+void Platform::getSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
 {
     if (accelX)
     {

+ 6 - 6
gameplay/src/PlatformWindows.cpp

@@ -10,7 +10,7 @@
 #include <GL/wglew.h>
 #include <windowsx.h>
 #include <shellapi.h>
-#ifdef USE_XINPUT
+#ifdef GP_USE_GAMEPAD
 #include <XInput.h>
 #endif
 
@@ -38,7 +38,7 @@ static bool __multiSampling = false;
 static bool __cursorVisible = true;
 static unsigned int __gamepadsConnected = 0;
 
-#ifdef USE_XINPUT
+#ifdef GP_USE_GAMEPAD
 static const unsigned int XINPUT_BUTTON_COUNT = 14;
 static const unsigned int XINPUT_JOYSTICK_COUNT = 2;
 static const unsigned int XINPUT_TRIGGER_COUNT = 2;
@@ -950,7 +950,7 @@ Platform* Platform::create(Game* game, void* attachToWindow)
             goto error;
     }
 
-#ifdef USE_XINPUT
+#ifdef GP_USE_GAMEPAD
     // Initialize XInputGamepads.
     for (DWORD i = 0; i < XUSER_MAX_COUNT; i++)
     {
@@ -1012,7 +1012,7 @@ int Platform::enterMessagePump()
         }
         else
         {
-#ifdef USE_XINPUT
+#ifdef GP_USE_GAMEPAD
             // Check for connected XInput gamepads.
             for (DWORD i = 0; i < XUSER_MAX_COUNT; i++)
             {
@@ -1150,7 +1150,7 @@ void Platform::getAccelerometerValues(float* pitch, float* roll)
     *roll = 0;
 }
 
-void Platform::getRawSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
+void Platform::getSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
 {
     if (accelX)
     {
@@ -1262,7 +1262,7 @@ bool Platform::isGestureRegistered(Gesture::GestureEvent evt)
     return false;
 }
 
-#ifdef USE_XINPUT
+#ifdef GP_USE_GAMEPAD
 void Platform::pollGamepadState(Gamepad* gamepad)
 {
     GP_ASSERT(gamepad->_handle < XUSER_MAX_COUNT);

+ 1 - 1
gameplay/src/PlatformiOS.mm

@@ -1417,7 +1417,7 @@ void Platform::getAccelerometerValues(float* pitch, float* roll)
     [__appDelegate getAccelerometerPitch:pitch roll:roll];
 }
 
-void Platform::getRawSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
+void Platform::getSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
 {
     float x, y, z;
     [__appDelegate getRawAccelX:&x Y:&y Z:&z];

+ 5 - 5
gameplay/src/Ref.cpp

@@ -5,7 +5,7 @@
 namespace gameplay
 {
 
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 void* trackRef(Ref* ref);
 void untrackRef(Ref* ref, void* record);
 #endif
@@ -13,7 +13,7 @@ void untrackRef(Ref* ref, void* record);
 Ref::Ref() :
     _refCount(1)
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
     __record = trackRef(this);
 #endif
 }
@@ -21,7 +21,7 @@ Ref::Ref() :
 Ref::Ref(const Ref& copy) :
     _refCount(1)
 {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
     __record = trackRef(this);
 #endif
 }
@@ -39,7 +39,7 @@ void Ref::release()
 {
     if ((--_refCount) <= 0)
     {
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
         untrackRef(this, __record);
 #endif
         delete this;
@@ -51,7 +51,7 @@ unsigned int Ref::getRefCount() const
     return _refCount;
 }
 
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#ifdef GP_USE_MEM_LEAK_DETECTION
 
 struct RefAllocationRecord
 {

+ 2 - 2
gameplay/src/Ref.h

@@ -66,8 +66,8 @@ private:
 
     unsigned int _refCount;
 
-    // Memory leak diagnostic data (only included when GAMEPLAY_MEM_LEAK_DETECTION is defined)
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+    // Memory leak diagnostic data (only included when GP_USE_MEM_LEAK_DETECTION is defined)
+#ifdef GP_USE_MEM_LEAK_DETECTION
     friend class Game;
     static void printLeaks();
     void* __record;

+ 18 - 0
gameplay/src/SocialAchievement.cpp

@@ -0,0 +1,18 @@
+#include "Base.h"
+#include "SocialAchievement.h"
+
+namespace gameplay
+{
+
+SocialAchievement::SocialAchievement()
+    : value(0), total(0), percentCompleted(0.0f)
+{
+}
+
+SocialAchievement::~SocialAchievement()
+{
+}
+
+}
+
+

+ 58 - 0
gameplay/src/SocialAchievement.h

@@ -0,0 +1,58 @@
+#ifndef SOCIALACHIEVEMENT_H_
+#define SOCIALACHIEVEMENT_H_
+
+namespace gameplay
+{
+
+/**
+ * Defines a class for typical social game activities running with an autenicated session.
+ */
+class SocialAchievement
+{
+
+public:
+
+    /**
+     * The name/title of the achievement.
+     */
+    std::string name;
+
+    /**
+     * The value of progress (0 to getTotal) representing the current unit value of completion.
+     */
+    unsigned int value;
+
+    /**
+     * The total value of progress needed to complete the achievement.
+     */
+    unsigned int total;
+
+    /**
+     * The percent that the achievement is complete. Equivalent to getValue() / getTotal() * 100.0f
+     */
+    float percentCompleted;
+
+    /**
+     * The date/time the achievement was achieved. (UTC string format "2013-06-27T07:40::05")
+     */
+    std::string dateTimeAchieved;
+
+    /**
+     * The provider handle for an achievement.
+     */
+    SocialAchievementHandle handle;
+
+    /**
+     * Constructor.
+     */
+    SocialAchievement();
+
+    /**
+     * Destructor.
+     */
+    ~SocialAchievement();
+};
+
+}
+
+#endif

+ 46 - 0
gameplay/src/SocialController.cpp

@@ -0,0 +1,46 @@
+#include "Base.h"
+#include "SocialController.h"
+#include "Game.h"
+#include "social/ScoreloopSocialSession.h"
+
+namespace gameplay
+{
+
+SocialController::SocialController()
+    : _session(NULL)
+{
+}
+
+SocialController::~SocialController()
+{
+}
+
+void SocialController::initialize()
+{
+}
+
+void SocialController::finalize()
+{
+}
+
+void SocialController::update(float elapsedTime)
+{
+}
+
+void SocialController::authenticate(SocialSessionListener* listener)
+{
+#if defined(__QNX__) && defined(GP_USE_SOCIAL)
+    Properties* socialProperties = Game::getInstance()->getConfig()->getNamespace("social");
+    const char* providerStr = socialProperties->getString("provider");
+    if(strcmp(providerStr, "Scoreloop") == 0)
+    {
+        ScoreloopSocialSession::authenticate(listener, socialProperties);
+    }
+    else
+    {
+        listener->authenticateEvent(SocialSessionListener::ERROR_INITIALIZATION, NULL);
+    }
+#endif
+}
+
+}

+ 86 - 0
gameplay/src/SocialController.h

@@ -0,0 +1,86 @@
+#ifndef SOCIALCONTROLLER_H_
+#define SOCIALCONTROLLER_H_
+
+#include "Properties.h"
+#include "SocialSession.h"
+#include "SocialSessionListener.h"
+
+namespace gameplay
+{
+
+/**
+ * Defines a class for controlling various back-end support for social capabilities.
+ *
+ * Back-end social providers include Friends, Leaderboards, Acheivements and Multiplayer.
+ * Social back-ends supported are Scoreloop, GameCenter and Google Play Game Services and Facebook.
+ * Configuration for these are specified in game.config:
+
+  @verbatim
+    social
+    {
+         provider = Scoreloop
+         id  = d346c484-12aa-49a2-a0a0-de2f87492d72
+         secret = aAa+DehBfyGO/CYaE3nWomgu7SIbWFczUih+Qwf3/n7u0y3nyq5Hag==
+         version = "1.0"
+         language = "en"
+         currency = "ASC"
+         leaderboard_mappings
+         {
+             // Format: leaderboardId = provider value
+             easy = 0
+             medium = 1
+             hard = 2
+         }
+    }
+
+ */
+class SocialController
+{
+    friend class Game;
+
+public:
+
+    /**
+     * Asyncrhonously authenicates a new user session.
+     *
+     * @param listener The listener
+     */
+    void authenticate(SocialSessionListener* listener);
+
+private:
+
+    /**
+     * Constructor.
+     */
+    SocialController();
+
+    /**
+     * Destructor.
+     */
+    ~SocialController();
+
+    /**
+     * Callback for when the controller is initialized.
+     */
+    void initialize();
+
+    /*
+     * Callback for when the controller is finalized.
+     */
+    void finalize();
+
+    /**
+     * Callback for when the controller receives a frame update event.
+     */
+    void update(float elapsedTime);
+
+private:
+
+    SocialSession* _session;
+
+};
+
+}
+
+#endif
+

+ 17 - 0
gameplay/src/SocialPlayer.cpp

@@ -0,0 +1,17 @@
+#include "Base.h"
+#include "SocialPlayer.h"
+
+namespace gameplay
+{
+
+SocialPlayer::SocialPlayer()
+{
+}
+
+SocialPlayer::~SocialPlayer()
+{
+}
+
+}
+
+

+ 40 - 0
gameplay/src/SocialPlayer.h

@@ -0,0 +1,40 @@
+#ifndef SOCIALPLAYER_H_
+#define SOCIALPLAYER_H_
+
+namespace gameplay
+{
+
+/**
+ * Defines a social player.
+ *
+ * This can either be the authenticated user, friend or community user (not friend yet...).
+ */
+class SocialPlayer
+{
+
+public:
+
+    /**
+     * The players friendly name.
+     */
+    std::string name;
+
+    /**
+     * The provider handle for a player.
+     */
+    SocialPlayerHandle handle;
+
+    /**
+     * Constructor
+     */
+    SocialPlayer();
+
+    /**
+     * Destructor
+     */
+    ~SocialPlayer();
+};
+
+}
+
+#endif

+ 18 - 0
gameplay/src/SocialScore.cpp

@@ -0,0 +1,18 @@
+#include "Base.h"
+#include "SocialScore.h"
+
+namespace gameplay
+{
+
+SocialScore::SocialScore()
+    : value(0.0f), rank(0)
+{
+}
+
+SocialScore::~SocialScore()
+{
+}
+
+}
+
+

+ 52 - 0
gameplay/src/SocialScore.h

@@ -0,0 +1,52 @@
+#ifndef SOCIALSCORE_H_
+#define SOCIALSCORE_H_
+
+namespace gameplay
+{
+
+/**
+ * Defines an abstract class for a score that resides in a leaderboard
+ */
+class SocialScore
+{
+public:
+
+    /**
+     * The value for the score.
+     */
+    float value;
+
+    /**
+     * The formatted value for the score.
+     */
+    std::string valueFormatted;
+
+    /**
+     * The rank index of the score within the leaderboard.
+     */
+    unsigned int rank;
+
+    /**
+     * The handle of the player that achieved the score
+     */
+    std::string playerName;
+
+    /**
+     * The score
+     */
+    SocialScoreHandle handle;
+
+    /**
+     * Constructor
+     */
+    SocialScore();
+
+    /**
+     * Destructor
+     */
+    ~SocialScore();
+};
+
+}
+
+#endif

+ 90 - 0
gameplay/src/SocialSession.h

@@ -0,0 +1,90 @@
+#ifndef SOCIALSESSION_H_
+#define SOCIALSESSION_H_
+
+#include "SocialSessionListener.h"
+#include "SocialPlayer.h"
+#include "SocialAchievement.h"
+#include "SocialScore.h"
+#include "Properties.h"
+
+namespace gameplay
+{
+
+/**
+ * Defines an abstract class for typical social game activities running with an authenticated session.
+ */
+class SocialSession
+{
+    friend class SocialController;
+
+public:
+
+    enum CommunityScope
+    {
+        COMMUNITY_SCOPE_FRIENDS,
+        COMMUNITY_SCOPE_ALL,
+    };
+
+    enum TimeScope
+    {
+        TIME_SCOPE_TODAY,
+        TIME_SCOPE_WEEK,
+        TIME_SCOPE_ALL,
+    };
+
+    /**
+     * Gets the asynchronous response listener that registered for this session.
+     *
+     * @return The asynchronous response listener that registered for this session.
+     */
+    virtual SocialSessionListener* getListener() = 0;
+
+    virtual SocialPlayer* getUser() = 0;
+
+    virtual void loadFriends() = 0;
+
+    virtual void loadAchievements() = 0;
+
+    virtual void submitAchievement(const char* achievementId, unsigned int value) = 0;
+
+    /**
+     * Asynchronously request the scores for the count where the player is in the middle.
+     *
+     * @param leaderboardId The leaderboard to get populated witth the scores.
+     * @param community The community scope to filter the search list.
+     * @param time The time scope to filter teh search list.
+     * @param player The player to narrow the search around.
+     * @param count The number to scores return in the result.
+     */
+    virtual void loadScores(const char* leaderboardId, CommunityScope community, TimeScope time, const SocialPlayer& player, unsigned int count) = 0;
+
+    /**
+     * Asynchronously request the scores for a specified leaderboard for this game.
+     *
+     * @param leaderboardId The leaderboard to get populated witth the scores.
+     */
+    virtual void loadScores(const char* leaderboardId, CommunityScope community, TimeScope time, unsigned int start, unsigned int count) = 0;
+
+    virtual void submitScore(const char* leaderboardId, float value) = 0;
+
+    virtual void loadSavedData(const char* key) = 0;
+
+    virtual void submitSavedData(const char* key, std::string data) = 0;
+
+protected:
+
+    /**
+     * Contructor
+     */
+    SocialSession() { }
+
+    /**
+     * Destructor
+     */
+    virtual ~SocialSession() { }
+
+};
+
+}
+
+#endif

+ 52 - 0
gameplay/src/SocialSessionListener.cpp

@@ -0,0 +1,52 @@
+#include "Base.h"
+#include "SocialSessionListener.h"
+
+namespace gameplay
+{
+SocialSessionListener::SocialSessionListener()
+{
+}
+
+SocialSessionListener::SocialSessionListener(const SocialSessionListener& copy)
+{
+}
+
+SocialSessionListener::~SocialSessionListener()
+{
+}
+
+void SocialSessionListener::authenticateEvent(ResponseCode code, SocialSession* session)
+{
+}
+
+void SocialSessionListener::loadFriendsEvent(ResponseCode code, std::vector<SocialPlayer> friends)
+{
+}
+
+void SocialSessionListener::loadAchievementsEvent(ResponseCode code, std::vector<SocialAchievement> achievements)
+{
+}
+
+void SocialSessionListener::submitAchievementEvent(ResponseCode code)
+{
+}
+
+void SocialSessionListener::loadScoresEvent(ResponseCode code, std::vector<SocialScore> scores)
+{
+}
+
+void SocialSessionListener::submitScoreEvent(ResponseCode code)
+{
+}
+
+void SocialSessionListener::loadSavedDataEvent(ResponseCode code, std::string data)
+{
+}
+
+void SocialSessionListener::submitSavedDataEvent(ResponseCode code)
+{
+}
+
+}
+
+

+ 70 - 0
gameplay/src/SocialSessionListener.h

@@ -0,0 +1,70 @@
+#ifndef SOCIALSESSIONLISTENER_H_
+#define SOCIALSESSIONLISTENER_H_
+
+#include "SocialPlayer.h"
+#include "SocialAchievement.h"
+#include "SocialScore.h"
+
+namespace gameplay
+{
+
+class SocialSession;
+
+/**
+ * Defines a class for handling session responses to various session request.
+ */
+class SocialSessionListener
+{
+public:
+
+    /**
+     * Constructor
+     */
+    SocialSessionListener();
+
+    /**
+     * Constructor
+     */
+    SocialSessionListener(const SocialSessionListener& copy);
+
+    /**
+     * Destructor
+     */
+    virtual ~SocialSessionListener();
+
+    /**
+     * Response codes returned on listener events.
+     */
+    enum ResponseCode
+    {
+        SUCCESS = 0,
+        ERROR_INITIALIZATION,
+        ERROR_PENDING_RESPONSE,
+        ERROR_INVALID_USER,
+        ERROR_INVALID_ARG,
+        ERROR_SERVER,
+        ERROR_UNKNOWN
+    };
+
+    virtual void authenticateEvent(ResponseCode code, SocialSession* session);
+
+    virtual void loadFriendsEvent(ResponseCode code, std::vector<SocialPlayer> friends);
+
+    virtual void loadAchievementsEvent(ResponseCode code, std::vector<SocialAchievement> achievements);
+
+    virtual void submitAchievementEvent(ResponseCode code);
+
+    virtual void loadScoresEvent(ResponseCode code, std::vector<SocialScore> scores);
+
+    virtual void submitScoreEvent(ResponseCode code);
+
+    virtual void loadSavedDataEvent(ResponseCode code, std::string data);
+
+    virtual void submitSavedDataEvent(ResponseCode code);
+
+};
+
+}
+
+
+#endif

+ 9 - 1
gameplay/src/gameplay.h

@@ -88,7 +88,7 @@
 #include "AIState.h"
 #include "AIStateMachine.h"
 
-// UI
+// Forms UI
 #include "Theme.h"
 #include "Control.h"
 #include "Container.h"
@@ -105,3 +105,11 @@
 #include "AbsoluteLayout.h"
 #include "VerticalLayout.h"
 #include "FlowLayout.h"
+
+// Social
+#include "SocialController.h"
+#include "SocialSession.h"
+#include "SocialSessionListener.h"
+#include "SocialPlayer.h"
+#include "SocialAchievement.h"
+#include "SocialScore.h"

+ 4 - 37
gameplay/src/lua/lua_Game.cpp

@@ -44,8 +44,8 @@ void luaRegister_Game()
         {"getGamepadCount", lua_Game_getGamepadCount},
         {"getHeight", lua_Game_getHeight},
         {"getPhysicsController", lua_Game_getPhysicsController},
-        {"getRawSensorValues", lua_Game_getRawSensorValues},
         {"getScriptController", lua_Game_getScriptController},
+        {"getSensorValues", lua_Game_getSensorValues},
         {"getState", lua_Game_getState},
         {"getViewport", lua_Game_getViewport},
         {"getWidth", lua_Game_getWidth},
@@ -60,7 +60,6 @@ void luaRegister_Game()
         {"isMultiTouch", lua_Game_isMultiTouch},
         {"keyEvent", lua_Game_keyEvent},
         {"launchURL", lua_Game_launchURL},
-        {"menuEvent", lua_Game_menuEvent},
         {"mouseEvent", lua_Game_mouseEvent},
         {"pause", lua_Game_pause},
         {"registerGesture", lua_Game_registerGesture},
@@ -1070,7 +1069,7 @@ int lua_Game_getPhysicsController(lua_State* state)
     return 0;
 }
 
-int lua_Game_getRawSensorValues(lua_State* state)
+int lua_Game_getSensorValues(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -1107,12 +1106,12 @@ int lua_Game_getRawSensorValues(lua_State* state)
                 gameplay::ScriptUtil::LuaArray<float> param6 = gameplay::ScriptUtil::getFloatPointer(7);
 
                 Game* instance = getInstance(state);
-                instance->getRawSensorValues(param1, param2, param3, param4, param5, param6);
+                instance->getSensorValues(param1, param2, param3, param4, param5, param6);
                 
                 return 0;
             }
 
-            lua_pushstring(state, "lua_Game_getRawSensorValues - Failed to match the given parameters to a valid function signature.");
+            lua_pushstring(state, "lua_Game_getSensorValues - Failed to match the given parameters to a valid function signature.");
             lua_error(state);
             break;
         }
@@ -1686,38 +1685,6 @@ int lua_Game_launchURL(lua_State* state)
     return 0;
 }
 
-int lua_Game_menuEvent(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
-
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 1:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA))
-            {
-                Game* instance = getInstance(state);
-                instance->menuEvent();
-                
-                return 0;
-            }
-
-            lua_pushstring(state, "lua_Game_menuEvent - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 1).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
 int lua_Game_mouseEvent(lua_State* state)
 {
     // Get the number of parameters.

+ 1 - 2
gameplay/src/lua/lua_Game.h

@@ -27,8 +27,8 @@ int lua_Game_getGamepad(lua_State* state);
 int lua_Game_getGamepadCount(lua_State* state);
 int lua_Game_getHeight(lua_State* state);
 int lua_Game_getPhysicsController(lua_State* state);
-int lua_Game_getRawSensorValues(lua_State* state);
 int lua_Game_getScriptController(lua_State* state);
+int lua_Game_getSensorValues(lua_State* state);
 int lua_Game_getState(lua_State* state);
 int lua_Game_getViewport(lua_State* state);
 int lua_Game_getWidth(lua_State* state);
@@ -43,7 +43,6 @@ int lua_Game_isMultiSampling(lua_State* state);
 int lua_Game_isMultiTouch(lua_State* state);
 int lua_Game_keyEvent(lua_State* state);
 int lua_Game_launchURL(lua_State* state);
-int lua_Game_menuEvent(lua_State* state);
 int lua_Game_mouseEvent(lua_State* state);
 int lua_Game_pause(lua_State* state);
 int lua_Game_registerGesture(lua_State* state);

+ 698 - 0
gameplay/src/social/ScoreloopSocialSession.cpp

@@ -0,0 +1,698 @@
+#if defined(__QNX__) && defined(GP_USE_SOCIAL)
+
+#include "Base.h"
+#include "ScoreloopSocialSession.h"
+
+namespace gameplay
+{
+
+ScoreloopSocialSession* ScoreloopSocialSession::_session = NULL;
+
+ScoreloopSocialSession::ScoreloopSocialSession()
+    : SocialSession(),
+      _listener(NULL), _properties(NULL), _pendingResponse(false),
+      _client(NULL), _userController(NULL), _usersController(NULL),
+      _localAchievementsController(NULL), _scoresController(NULL), _scoreController(NULL),
+      _key(NULL)
+{
+    pthread_cond_init(&_channelCond, NULL);
+    pthread_mutex_init(&_channelMutex, NULL);
+    _userOp = USEROP_GET_LOCALUSER;
+}
+
+ScoreloopSocialSession::~ScoreloopSocialSession()
+{
+}
+
+SocialSessionListener* ScoreloopSocialSession::getListener()
+{
+    return _listener;
+}
+
+void* ScoreloopSocialSession::platformEventCallback(void* data)
+{
+    _session = (ScoreloopSocialSession*)data;
+
+    int rc = bps_initialize();
+
+    if (rc == BPS_FAILURE)
+        GP_ERROR("ScoreloopSocialSession::platformEventHandler - bps_initialize failed.");
+
+    pthread_mutex_lock(&_session->_channelMutex);
+    pthread_mutex_unlock(&_session->_channelMutex);
+    pthread_cond_signal(&_session->_channelCond);
+
+    bps_event_t* event = NULL;
+    while (true)
+    {
+        rc = bps_get_event(&event, -1);
+
+        if (rc == BPS_FAILURE)
+            GP_ERROR("ScoreloopSocialSession::platformEventHandler - bps_get_event failed.");
+
+        if (bps_event_get_domain(event) == SC_GetBPSEventDomain(&_session->_initData))
+        {
+            SC_HandleBPSEvent(&_session->_initData, event);
+        }
+    }
+    bps_shutdown();
+    return 0;
+}
+
+void ScoreloopSocialSession::authenicate(SocialSessionListener* listener, Properties* properties)
+{
+    if (_session)
+        return;
+
+    _session = new ScoreloopSocialSession();
+    _session->_listener = listener;
+    _session->_properties = properties;
+
+    const char* gameId = properties->getString("game_id");
+    const char* gameSecret = properties->getString("game_secret");
+    const char* gameVersion = properties->getString("game_version");
+    const char* gameCurrency = properties->getString("game_currency");
+    const char* gameLanguage = properties->getString("gameLanguage");
+
+    SC_InitData_Init(&_session->_initData);
+    SC_Error_t rc = SC_Client_New(&_session->_client, &_session->_initData, gameId, gameSecret, gameVersion, gameCurrency, gameLanguage);
+    if (rc != SC_OK)
+    {
+        listener->authenticateEvent(SocialSessionListener::ERROR_INITIALIZATION, NULL);
+        return;
+    }
+
+    rc = SC_Client_CreateUserController(_session->_client, &_session->_userController, ScoreloopSocialSession::userCallback, _session);
+    if (rc != SC_OK)
+    {
+        listener->authenticateEvent(SocialSessionListener::ERROR_INITIALIZATION, NULL);
+        return;
+    }
+
+    rc = SC_UserController_LoadUser(_session->_userController);
+    if (rc != SC_OK)
+    {
+        SC_UserController_Release(_session->_userController);
+        _session->_userController = NULL;
+        listener->authenticateEvent(SocialSessionListener::ERROR_INITIALIZATION, NULL);
+    }
+
+    // Create thread for platform event handler needed by Scoreloop
+    pthread_mutex_lock(&_session->_channelMutex);
+    pthread_create(NULL, NULL, platformEventCallback, _session);
+    pthread_cond_wait(&_session->_channelCond, &_session->_channelMutex);
+    pthread_mutex_unlock(&_session->_channelMutex);
+}
+
+void ScoreloopSocialSession::userCallback(void* cookie, SC_Error_t result)
+{
+    ScoreloopSocialSession* session = (ScoreloopSocialSession*)cookie;
+
+    switch (result)
+    {
+    case SC_OK:
+        {
+            switch(session->_userOp)
+            {
+            case USEROP_GET_LOCALUSER:
+                {
+                    session->_user.handle =  SC_UserController_GetUser(session->_userController);
+                    SC_String_h name = SC_User_GetLogin(session->_user.handle);
+                    session->_user.name = SC_String_GetData(name);
+                    session->getListener()->authenticateEvent(SocialSessionListener::SUCCESS, session);
+                }
+                break;
+            case USEROP_WRITE_CONTEXT:
+                {
+                    session->getListener()->submitSavedDataEvent(SocialSessionListener::SUCCESS);
+                }
+                break;
+            case USEROP_READ_CONTEXT:
+                {
+                    SC_Context_h context = SC_User_GetContext(session->_user.handle);
+                    SC_String_h str;
+                    SC_Error_t rc = SC_Context_Get(context, session->_key, &str);
+                    if (rc != SC_OK)
+                    {
+                        session->getListener()->loadSavedDataEvent(SocialSessionListener::ERROR_INVALID_ARG, "");
+                    }
+                    else
+                    {
+                        session->getListener()->loadSavedDataEvent(SocialSessionListener::SUCCESS, std::string(SC_String_GetData(str)));
+                    }
+                }
+                break;
+            }
+        }
+        break;
+
+    case SC_INVALID_USER_DATA:
+        {
+            switch(session->_userOp)
+            {
+                case USEROP_GET_LOCALUSER:
+                    session->getListener()->authenticateEvent(SocialSessionListener::ERROR_INVALID_USER, NULL);
+                    break;
+                case USEROP_WRITE_CONTEXT:
+                    session->getListener()->submitSavedDataEvent(SocialSessionListener::ERROR_INVALID_USER);
+                    break;
+                case USEROP_READ_CONTEXT:
+                    session->getListener()->loadSavedDataEvent(SocialSessionListener::ERROR_INVALID_USER, "");
+                    break;
+            }
+        }
+        break;
+
+    case SC_HTTP_SERVER_ERROR:
+        {
+            switch(session->_userOp)
+            {
+                case USEROP_GET_LOCALUSER:
+                    session->getListener()->authenticateEvent(SocialSessionListener::ERROR_SERVER, NULL);
+                    break;
+                case USEROP_WRITE_CONTEXT:
+                    session->getListener()->submitSavedDataEvent(SocialSessionListener::ERROR_SERVER);
+                    break;
+                case USEROP_READ_CONTEXT:
+                    session->getListener()->loadSavedDataEvent(SocialSessionListener::ERROR_SERVER, "");
+                    break;
+            }
+        }
+        break;
+
+    default:
+        {
+            switch(session->_userOp)
+            {
+                case USEROP_GET_LOCALUSER:
+                    session->getListener()->authenticateEvent(SocialSessionListener::ERROR_UNKNOWN, NULL);
+                    break;
+                case USEROP_WRITE_CONTEXT:
+                    session->getListener()->submitSavedDataEvent(SocialSessionListener::ERROR_UNKNOWN);
+                    break;
+                case USEROP_READ_CONTEXT:
+                    session->getListener()->loadSavedDataEvent(SocialSessionListener::ERROR_UNKNOWN, "");
+                    break;
+            }
+        }
+        break;
+    }
+    session->_pendingResponse = false;
+}
+
+void ScoreloopSocialSession::loadFriends()
+{
+    if (_pendingResponse)
+    {
+        _listener->loadFriendsEvent(SocialSessionListener::ERROR_PENDING_RESPONSE, _friends);
+        return;
+    }
+    _pendingResponse = true;
+
+    // Create a scoreloop users controller (for finding friends)
+    SC_Error_t rc;
+    if (_usersController == NULL)
+    {
+        rc = SC_Client_CreateUsersController(_client, &_usersController, ScoreloopSocialSession::loadFriendsCallback, this);
+        if (rc != SC_OK)
+        {
+            _listener->loadFriendsEvent(SocialSessionListener::ERROR_INITIALIZATION, _friends);
+            return;
+        }
+    }
+    rc = SC_UsersController_LoadBuddies(_usersController, _user.handle);
+    if (rc != SC_OK)
+   {
+       SC_UsersController_Release(_usersController);
+       _usersController = NULL;
+       _listener->loadFriendsEvent(SocialSessionListener::ERROR_INITIALIZATION, _friends);
+   }
+}
+
+void ScoreloopSocialSession::loadFriendsCallback(void* cookie, SC_Error_t result)
+{
+    ScoreloopSocialSession* session = (ScoreloopSocialSession*)cookie;
+    switch (result)
+    {
+    case SC_OK:
+        {
+            SC_UserList_h usersList = SC_UsersController_GetUsers(session->_usersController);
+            unsigned int usersCount = SC_UserList_GetCount(usersList);
+            session->_friends.clear();
+            for (unsigned int i = 0; i < usersCount; i++)
+            {
+                SocialPlayer player;
+                player.handle = SC_UserList_GetAt(usersList, i);
+                SC_UserController_GetUser(session->_userController);
+                SC_String_h name = SC_User_GetLogin(player.handle);
+                player.name = SC_String_GetData(name);
+                session->_friends.push_back(player);
+            }
+            session->getListener()->loadFriendsEvent(SocialSessionListener::SUCCESS, session->_friends);
+        }
+        break;
+    case SC_INVALID_USER_DATA:
+        session->getListener()->loadFriendsEvent(SocialSessionListener::ERROR_INVALID_USER, session->_friends);
+        break;
+    case SC_HTTP_SERVER_ERROR:
+        session->getListener()->loadFriendsEvent(SocialSessionListener::ERROR_SERVER, session->_friends);
+        break;
+    default:
+        session->getListener()->loadFriendsEvent(SocialSessionListener::ERROR_UNKNOWN, session->_friends);
+        break;
+    }
+    session->_pendingResponse = false;
+}
+
+void ScoreloopSocialSession::loadAchievements()
+{
+    if (_pendingResponse)
+    {
+        _listener->loadAchievementsEvent(SocialSessionListener::ERROR_PENDING_RESPONSE, _achievements);
+        return;
+    }
+    _pendingResponse = true;
+
+    SC_Error_t rc;
+    rc = SC_Client_CreateLocalAchievementsController(_client, &_localAchievementsController, ScoreloopSocialSession::loadAchievementsCallback, this);
+    if (rc != SC_OK)
+    {
+        _listener->loadAchievementsEvent(SocialSessionListener::ERROR_INITIALIZATION, _achievements);
+        return;
+    }
+
+    if (SC_LocalAchievementsController_ShouldSynchronize(_localAchievementsController))
+    {
+        rc = SC_LocalAchievementsController_Synchronize(_localAchievementsController);
+        {
+            SC_LocalAchievementsController_Release(_localAchievementsController);
+            _localAchievementsController = NULL;
+            _listener->loadAchievementsEvent(SocialSessionListener::ERROR_INITIALIZATION, _achievements);
+        }
+    }
+    else
+    {
+        ScoreloopSocialSession::loadAchievementsCallback(this, SC_OK);
+    }
+}
+
+void ScoreloopSocialSession::loadAchievementsCallback(void* cookie, SC_Error_t result)
+{
+    ScoreloopSocialSession* session = (ScoreloopSocialSession*)cookie;
+    switch (result)
+    {
+    case SC_OK:
+        {
+            SC_AchievementList_h achievementsList = SC_LocalAchievementsController_GetAchievements(session->_localAchievementsController);
+            unsigned int achievementsCount = SC_AchievementList_GetCount(achievementsList);
+            session->_achievements.clear();
+            for (unsigned int i = 0; i < achievementsCount; i++)
+            {
+                SocialAchievement achievement;
+                achievement.handle = SC_AchievementList_GetAt(achievementsList, i);
+                SC_String_h id = SC_Achievement_GetIdentifier(achievement.handle);
+                achievement.name = SC_String_GetData(id);
+                achievement.value = (unsigned int) SC_Achievement_GetValue(achievement.handle);
+                SC_Award_h award = SC_Achievement_GetAward(achievement.handle);
+                achievement.total = SC_Award_GetAchievingValue(award);
+                achievement.percentCompleted = achievement.value == 0 ? 0.0f : ((float)achievement.value / (float)achievement.total) * 100.f;
+                SC_String_h dateTime = SC_Achievement_GetDate(achievement.handle);
+                achievement.dateTimeAchieved = SC_String_GetData(id);
+                session->_achievements.push_back(achievement);
+            }
+            session->getListener()->loadAchievementsEvent(SocialSessionListener::SUCCESS, _session->_achievements);
+        }
+        break;
+    case SC_INVALID_USER_DATA:
+        session->getListener()->loadAchievementsEvent(SocialSessionListener::ERROR_INVALID_USER, _session->_achievements);
+        break;
+    case SC_HTTP_SERVER_ERROR:
+        session->getListener()->loadAchievementsEvent(SocialSessionListener::ERROR_SERVER, _session->_achievements);
+        break;
+    default:
+        session->getListener()->loadAchievementsEvent(SocialSessionListener::ERROR_UNKNOWN, _session->_achievements);
+        break;
+    }
+    session->_pendingResponse = false;
+}
+
+void ScoreloopSocialSession::submitAchievement(const char* achievementId, unsigned int value)
+{
+    if (_pendingResponse)
+    {
+        _listener->submitAchievementEvent(SocialSessionListener::ERROR_PENDING_RESPONSE);
+        return;
+    }
+    _pendingResponse = true;
+
+    SC_Error_t rc;
+    rc = SC_Client_CreateLocalAchievementsController(_client, &_localAchievementsController, ScoreloopSocialSession::submitAchievementCallback, this);
+    if (rc != SC_OK)
+    {
+        _listener->submitAchievementEvent(SocialSessionListener::ERROR_INITIALIZATION);
+    }
+    SC_Bool_t achieved;
+    rc = SC_LocalAchievementsController_SetValueForAwardIdentifier(_localAchievementsController, achievementId, value, &achieved);
+
+    if (rc != SC_OK)
+    {
+        SC_LocalAchievementsController_Release(_localAchievementsController);
+        _localAchievementsController = NULL;
+      _listener->submitAchievementEvent(SocialSessionListener::ERROR_INITIALIZATION);
+    }
+}
+
+void ScoreloopSocialSession::submitAchievementCallback(void* cookie, SC_Error_t result)
+{
+    ScoreloopSocialSession* session = (ScoreloopSocialSession*)cookie;
+    switch (result)
+    {
+    case SC_OK:
+        session->getListener()->submitAchievementEvent(SocialSessionListener::SUCCESS);
+        break;
+    case SC_INVALID_USER_DATA:
+        session->getListener()->submitAchievementEvent(SocialSessionListener::ERROR_INVALID_USER);
+        break;
+    case SC_HTTP_SERVER_ERROR:
+        session->getListener()->submitAchievementEvent(SocialSessionListener::ERROR_SERVER);
+        break;
+    default:
+        session->getListener()->submitAchievementEvent(SocialSessionListener::ERROR_UNKNOWN);
+        break;
+    }
+    session->_pendingResponse = false;
+}
+
+void ScoreloopSocialSession::loadScores(const char* leaderboardId, CommunityScope community, TimeScope time, const SocialPlayer& player, unsigned int count)
+{
+    if (_pendingResponse)
+     {
+         _listener->loadScoresEvent(SocialSessionListener::ERROR_PENDING_RESPONSE, _scores);
+         return;
+     }
+     _pendingResponse = true;
+
+    SC_Error_t rc;
+    if (_scoresController == NULL)
+    {
+        rc = SC_Client_CreateScoresController(_client, &_scoresController, ScoreloopSocialSession::loadScoresCallback, this);
+        if (rc != SC_OK)
+        {
+            _listener->loadScoresEvent(SocialSessionListener::ERROR_INITIALIZATION, _scores);
+            return;
+        }
+    }
+
+    // Lookup the mode to be mapped for the specified leaderboard id
+    if (leaderboardId != NULL)
+    {
+        Properties* leaderboardMappings = _properties->getNamespace("leaderboard_mappings", false);
+        if (leaderboardMappings)
+        {
+            int mode = leaderboardMappings->getInt(leaderboardId);
+            if (mode >=  0)
+            {
+                SC_ScoresController_SetMode(_scoresController, (unsigned int)mode);
+            }
+        }
+    }
+
+    // Set the search list filter
+    SC_ScoresSearchList_t searchList = SC_SCORES_SEARCH_LIST_USER_COUNTRY;
+    switch(community)
+    {
+    case COMMUNITY_SCOPE_FRIENDS:
+        searchList.usersSelector = SC_USERS_SELECTOR_BUDDYHOOD;
+        break;
+    case COMMUNITY_SCOPE_ALL:
+        searchList.usersSelector = SC_USERS_SELECTOR_ALL;
+        break;
+    }
+    switch(time)
+    {
+    case TIME_SCOPE_TODAY:
+        searchList.timeInterval = SC_TIME_INTERVAL_24H;
+        break;
+    case TIME_SCOPE_WEEK:
+            searchList.timeInterval = SC_TIME_INTERVAL_7DAYS;
+           break;
+    case TIME_SCOPE_ALL:
+            searchList.timeInterval = SC_TIME_INTERVAL_ALL;
+           break;
+    }
+    SC_ScoresController_SetSearchList(_scoresController, searchList);
+
+    // Specify the player and range count to get the scores around
+    SC_User_h user = player.handle;
+    rc = SC_ScoresController_LoadScoresAroundUser(_scoresController, _user.handle, count);
+    if (rc != SC_OK)
+    {
+      SC_ScoresController_Release(_scoresController);
+      _scoresController = NULL;
+      _listener->loadScoresEvent(SocialSessionListener::ERROR_INITIALIZATION, _scores);
+    }
+}
+
+void ScoreloopSocialSession::loadScores(const char* leaderboardId, CommunityScope community, TimeScope time, unsigned int start, unsigned int count)
+{
+    if (_pendingResponse)
+     {
+         _listener->loadScoresEvent(SocialSessionListener::ERROR_PENDING_RESPONSE, _scores);
+         return;
+     }
+     _pendingResponse = true;
+
+    SC_Error_t rc;
+    if (_scoresController == NULL)
+    {
+        rc = SC_Client_CreateScoresController(_client, &_scoresController, ScoreloopSocialSession::loadScoresCallback, this);
+        if (rc != SC_OK)
+        {
+            _listener->loadScoresEvent(SocialSessionListener::ERROR_INITIALIZATION, _scores);
+            return;
+        }
+    }
+
+    // Lookup the mode to be mapped for the specified leaderboard id
+    if (leaderboardId != NULL)
+    {
+        Properties* leaderboardMappings = _properties->getNamespace("leaderboard_mappings", false);
+        if (leaderboardMappings)
+        {
+
+            int mode = leaderboardMappings->getInt(leaderboardId);
+            if (mode >=  0)
+            {
+                SC_ScoresController_SetMode(_scoresController, (unsigned int)mode);
+            }
+        }
+    }
+
+    // Set the search list filter
+    SC_ScoresSearchList_t searchList = SC_SCORES_SEARCH_LIST_USER_COUNTRY;
+    switch(community)
+    {
+    case COMMUNITY_SCOPE_FRIENDS:
+        searchList.usersSelector = SC_USERS_SELECTOR_BUDDYHOOD;
+        break;
+    case COMMUNITY_SCOPE_ALL:
+        searchList.usersSelector = SC_USERS_SELECTOR_ALL;
+        break;
+    }
+    switch(time)
+    {
+    case TIME_SCOPE_TODAY:
+        searchList.timeInterval = SC_TIME_INTERVAL_24H;
+        break;
+    case TIME_SCOPE_WEEK:
+            searchList.timeInterval = SC_TIME_INTERVAL_7DAYS;
+           break;
+    case TIME_SCOPE_ALL:
+            searchList.timeInterval = SC_TIME_INTERVAL_ALL;
+           break;
+    }
+    SC_ScoresController_SetSearchList(_scoresController, searchList);
+
+    // Set the search range
+   SC_Range_t range;
+   range.offset = start;
+   range.length = count;
+   rc = SC_ScoresController_LoadScores(_scoresController, range);
+   if (rc != SC_OK)
+   {
+     SC_ScoresController_Release(_scoresController);
+     _scoresController = NULL;
+     _listener->loadScoresEvent(SocialSessionListener::ERROR_INITIALIZATION, _scores);
+   }
+}
+
+void ScoreloopSocialSession::loadScoresCallback(void* cookie, SC_Error_t result)
+{
+    ScoreloopSocialSession* session = (ScoreloopSocialSession*)cookie;
+    switch (result)
+    {
+    case SC_OK:
+        {
+            SC_ScoreFormatter_h scoreFormatter = SC_Client_GetScoreFormatter(session->_client);
+
+            SC_ScoreList_h scoresList = SC_ScoresController_GetScores(session->_scoresController);
+            unsigned int scoresCount = SC_ScoreList_GetCount(scoresList);
+            session->_scores.clear();
+            for (unsigned int i = 0; i < scoresCount; i++)
+            {
+                SocialScore score;
+                score.handle = SC_ScoreList_GetAt(scoresList, i);
+                score.rank = SC_Score_GetRank(score.handle);
+                score.value = (float)SC_Score_GetResult(score.handle);
+                SC_String_h formatted;
+                SC_ScoreFormatter_FormatScore(scoreFormatter, score.handle, SC_SCORE_FORMAT_DEFAULT, &formatted);
+                score.valueFormatted = SC_String_GetData(formatted);
+                SC_User_h player = SC_Score_GetUser(score.handle);
+                SC_String_h playerStr = SC_User_GetLogin(player);
+                score.playerName = SC_String_GetData(playerStr);
+                session->_scores.push_back(score);
+            }
+            session->getListener()->loadScoresEvent(SocialSessionListener::SUCCESS, session->_scores);
+        }
+        break;
+    case SC_INVALID_USER_DATA:
+        session->getListener()->loadScoresEvent(SocialSessionListener::ERROR_INVALID_USER, session->_scores);
+        break;
+    case SC_HTTP_SERVER_ERROR:
+        session->getListener()->loadScoresEvent(SocialSessionListener::ERROR_SERVER, session->_scores);
+        break;
+    default:
+        session->getListener()->loadScoresEvent(SocialSessionListener::ERROR_UNKNOWN, session->_scores);
+        break;
+    }
+    session->_pendingResponse = false;
+}
+
+void ScoreloopSocialSession::submitScore(const char* leaderboardId, float value)
+{
+    if (_pendingResponse)
+    {
+        _listener->submitScoreEvent(SocialSessionListener::ERROR_PENDING_RESPONSE);
+        return;
+    }
+    _pendingResponse = true;
+
+    SC_Error_t rc;
+    rc = SC_Client_CreateScoreController(_client, &_scoreController, ScoreloopSocialSession::submitScoreCallback, this);
+    if (rc != SC_OK)
+    {
+        _listener->submitScoreEvent(SocialSessionListener::ERROR_INITIALIZATION);
+        return;
+    }
+
+    // Create a score to submit
+    SC_Score_h score;
+    rc = SC_Client_CreateScore(_client, &score);
+    if (rc != SC_OK)
+    {
+        _listener->submitScoreEvent(SocialSessionListener::ERROR_INITIALIZATION);
+        return;
+    }
+
+    // Set the leaderboard to associate this score with
+    if (leaderboardId != NULL)
+    {
+        Properties* leaderboardMappings = _properties->getNamespace("leaderboard_mappings", false);
+        if (leaderboardMappings)
+        {
+            int mode = leaderboardMappings->getInt(leaderboardId);
+            if (mode >=  0)
+            {
+                SC_Score_SetMode(score, (unsigned int)mode);
+            }
+        }
+    }
+
+    // Set the score value and submit the score
+    SC_Score_SetResult(score, value);
+    rc = SC_ScoreController_SubmitScore(_scoreController, score);
+    if (rc != SC_OK)
+    {
+         SC_ScoreController_Release(_scoreController);
+         _scoreController = NULL;
+         _listener->submitScoreEvent(SocialSessionListener::ERROR_INITIALIZATION);
+    }
+    SC_Score_Release(score);
+}
+
+void ScoreloopSocialSession::submitScoreCallback(void* cookie, SC_Error_t result)
+{
+    ScoreloopSocialSession* session = (ScoreloopSocialSession*)cookie;
+    switch (result)
+    {
+    case SC_OK:
+        session->getListener()->submitScoreEvent(SocialSessionListener::SUCCESS);
+        break;
+    case SC_INVALID_USER_DATA:
+        session->getListener()->submitScoreEvent(SocialSessionListener::ERROR_INVALID_USER);
+        break;
+    case SC_HTTP_SERVER_ERROR:
+        session->getListener()->submitScoreEvent(SocialSessionListener::ERROR_SERVER);
+        break;
+    default:
+        session->getListener()->submitScoreEvent(SocialSessionListener::ERROR_UNKNOWN);
+        break;
+    }
+    session->_pendingResponse = false;
+}
+
+void ScoreloopSocialSession::loadSavedData(const char* key)
+{
+    if (_pendingResponse)
+    {
+        _listener->loadSavedDataEvent(SocialSessionListener::ERROR_PENDING_RESPONSE, "");
+        return;
+    }
+
+    SC_Error_t rc = SC_UserController_LoadUserContext(_userController);
+    if (rc != SC_OK)
+    {
+        _listener->loadSavedDataEvent(SocialSessionListener::ERROR_INITIALIZATION, "");
+        return;
+    }
+    _pendingResponse = true;
+    _key = key;
+}
+
+void ScoreloopSocialSession::submitSavedData(const char* key, std::string data)
+{
+    if (_pendingResponse)
+    {
+        _listener->submitSavedDataEvent(SocialSessionListener::ERROR_PENDING_RESPONSE);
+        return;
+    }
+    _pendingResponse = true;
+
+    SC_Context_h context;
+    SC_Error_t rc = SC_Context_New(&context);
+    if (rc != SC_OK)
+    {
+        _listener->submitSavedDataEvent(SocialSessionListener::ERROR_INITIALIZATION);
+        return;
+    }
+    SC_String_h str;
+    rc = SC_String_New(&str, data.c_str());
+    if (rc != SC_OK)
+    {
+        _listener->submitSavedDataEvent(SocialSessionListener::ERROR_INITIALIZATION);
+        return;
+    }
+    SC_Context_Put(context, key, str);
+    SC_User_SetContext(_user.handle, context);
+    SC_UserController_SetUser(_userController, _user.handle);
+    rc = SC_UserController_UpdateUserContext(_userController);
+    if (rc != SC_OK)
+    {
+        _listener->submitSavedDataEvent(SocialSessionListener::ERROR_INITIALIZATION);
+        return;
+    }
+}
+
+}
+
+#endif

+ 170 - 0
gameplay/src/social/ScoreloopSocialSession.h

@@ -0,0 +1,170 @@
+#if defined(__QNX__) && defined(GP_USE_SOCIAL)
+
+#ifndef SCORELOOPSOCIALSESSION_H_
+#define SCORELOOPSOCIALSESSION_H_
+
+#include "SocialSession.h"
+#include <scoreloop/sc_client.h>
+#include <scoreloop/sc_init.h>
+#include <pthread.h>
+
+namespace gameplay
+{
+
+/**
+ * Scoreloop implementation of SocialSession
+ *
+ * Note: ensure game.config has the following properties
+ *
+  @verbatim
+    social
+    {
+         provider = Scoreloop
+         id  = d346c484-12aa-49a2-a0a0-de2f87492d72
+         secret = aAa+DehBfyGO/CYaE3nWomgu7SIbWFczUih+Qwf3/n7u0y3nyq5Hag==
+         version = "1.0"
+         language = "en"
+         currency = "ASC"
+         leaderboard_mappings
+         {
+             // Format: leaderboardId =  mode <unsigned int>
+             easy = 0
+             medium = 1
+             hard = 2
+         }
+    }
+ *
+ * Note: Ensure your bar-descriptor.xml has:
+ *
+ * <action>read_device_identifying_information</action>
+ *
+ * @script{ignore}
+ */
+class ScoreloopSocialSession : public SocialSession
+{
+    friend class SocialController;
+
+public:
+
+    /**
+     * @see SocialSession::getListener
+     */
+    SocialSessionListener* getListener();
+
+    /**
+     * Initializes the session with the local client definition for this game.
+     *
+     * @param listener The listener for responses for this session
+     * @param properties The properties to initialize this session with for this game.
+     */
+    static void authenicate(SocialSessionListener* listener, Properties* properties);
+
+    /**
+     * @see SocialSession::getUser
+     */
+    SocialPlayer* getUser();
+
+    /**
+     * @see SocialSession::loadFriends
+     */
+    void loadFriends();
+
+    /**
+     * @see SocialSession::loadAchievements
+     */
+    void loadAchievements();
+
+    /**
+     * @see SocialSession::submitAchievement
+     */
+    void submitAchievement(const char* achievementId, unsigned int value);
+
+    /**
+     * @see SocialSession::loadScores
+     */
+    void loadScores(const char* leaderboardId, CommunityScope community, TimeScope time, const SocialPlayer& player, unsigned int count);
+
+    /**
+     * @see SocialSession::loadScores
+     */
+    void loadScores(const char* leaderboardId, CommunityScope community, TimeScope time, unsigned int start, unsigned int count);
+
+    /**
+     * @see SocialSession::submitScore
+     */
+    void submitScore(const char* leaderboardId, float score);
+
+    /**
+     * @see SocialSession::requestSavedData
+     */
+    void loadSavedData(const char* key);
+
+    /**
+     * @see SocialSession::submitSavedData
+     */
+    void submitSavedData(const char* key, std::string data);
+
+
+private:
+
+    /**
+     * Contructor
+     */
+    ScoreloopSocialSession();
+
+    /**
+     * Destructor
+     */
+    virtual ~ScoreloopSocialSession();
+
+    static void authenticate(SocialSessionListener* listener, Properties* properties);
+
+    static void* platformEventCallback(void* data);
+
+    static void userCallback(void* cookie, unsigned int result);
+
+    static void loadFriendsCallback(void* cookie, SC_Error_t result);
+
+    static void loadAchievementsCallback(void* cookie, SC_Error_t result);
+
+    static void submitAchievementCallback(void* cookie, SC_Error_t result);
+
+    static void loadScoresCallback(void* cookie, SC_Error_t result);
+
+    static void submitScoreCallback(void* cookie, SC_Error_t result);
+
+    static ScoreloopSocialSession* _session;
+
+    enum UserOp
+    {
+        USEROP_GET_LOCALUSER,
+        USEROP_WRITE_CONTEXT,
+        USEROP_READ_CONTEXT
+    };
+
+    SocialSessionListener* _listener;
+    Properties* _properties;
+    bool _pendingResponse;
+    SC_InitData_t _initData;
+    SC_Client_h _client;
+    SC_UserController_h _userController;
+    SC_UsersController_h _usersController;
+    SC_LocalAchievementsController_h _localAchievementsController;
+    SC_ScoresController_h _scoresController;
+    SC_ScoreController_h _scoreController;
+    pthread_cond_t _channelCond;
+    pthread_mutex_t _channelMutex;
+    const char* _key;
+    std::string _data;
+    SocialPlayer _user;
+    UserOp _userOp;
+    std::vector<SocialPlayer> _friends;
+    std::vector<SocialAchievement> _achievements;
+    std::vector<SocialScore> _scores;
+};
+
+}
+
+#endif
+
+#endif