Prechádzať zdrojové kódy

Merge branch 'next' of https://github.com/blackberry-gaming/GamePlay into next-kcunney

Kieran Cunney 14 rokov pred
rodič
commit
e6f56e188e

+ 32 - 0
gameplay-template/TEMPLATE_PROJECT-ios.plist

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string>icon.png</string>
+	<key>CFBundleIdentifier</key>
+	<string>TEMPLATE_UUID</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSApplicationCategoryType</key>
+	<string>public.app-category.games</string>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+</dict>
+</plist>

+ 0 - 0
gameplay-template/gameplay-template-macos.plist → gameplay-template/TEMPLATE_PROJECT-macos.plist


+ 210 - 35
gameplay-template/gameplay-template.xcodeproj/project.pbxproj

@@ -7,14 +7,14 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		42C932F11491A5160098216A /* TemplateGame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42C932EF1491A5160098216A /* TemplateGame.cpp */; };
+		42438B531491AD2000D218B8 /* libgameplay.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42438B521491AD2000D218B8 /* libgameplay.a */; };
+		42C932C11491A0DB0098216A /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C932C01491A0DB0098216A /* Cocoa.framework */; };
 		42C932EE1491A4CB0098216A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 42C932ED1491A4CB0098216A /* icon.png */; };
+		42C932F11491A5160098216A /* TemplateGame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42C932EF1491A5160098216A /* TemplateGame.cpp */; };
 		42C932F31491A53E0098216A /* res in Resources */ = {isa = PBXBuildFile; fileRef = 42C932F21491A53E0098216A /* res */; };
-		42C932C11491A0DB0098216A /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C932C01491A0DB0098216A /* Cocoa.framework */; };
-		42C9331D1491A6750098216A /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C9331C1491A6750098216A /* QuartzCore.framework */; };
 		42C933171491A5EB0098216A /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C933161491A5EB0098216A /* OpenGL.framework */; };
+		42C9331D1491A6750098216A /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C9331C1491A6750098216A /* QuartzCore.framework */; };
 		42C9331F1491A67F0098216A /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C9331E1491A67F0098216A /* OpenAL.framework */; };
-		42438B531491AD2000D218B8 /* libgameplay.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42438B521491AD2000D218B8 /* libgameplay.a */; };
 		42C933211491A6C70098216A /* libbullet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C933201491A6C70098216A /* libbullet.a */; };
 		42C933261491A6E50098216A /* libogg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C933221491A6E50098216A /* libogg.a */; };
 		42C933271491A6E50098216A /* libvorbis.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C933231491A6E50098216A /* libvorbis.a */; };
@@ -22,20 +22,37 @@
 		42C933291491A6E50098216A /* libvorbisfile.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C933251491A6E50098216A /* libvorbisfile.a */; };
 		42C9332C1491A7680098216A /* libpng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C9332A1491A7390098216A /* libpng.a */; };
 		42C9332F1491A78D0098216A /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C9332D1491A7810098216A /* libz.dylib */; };
+		5B61611314CCC2200073B857 /* TEMPLATE_PROJECT-macos.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5B61611214CCC2200073B857 /* TEMPLATE_PROJECT-macos.plist */; };
+		5B61611614CCC24C0073B857 /* TemplateGame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42C932EF1491A5160098216A /* TemplateGame.cpp */; };
+		5B61611814CCC24C0073B857 /* libgameplay.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42438B521491AD2000D218B8 /* libgameplay.a */; };
+		5B61611914CCC24C0073B857 /* libbullet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C933201491A6C70098216A /* libbullet.a */; };
+		5B61611A14CCC24C0073B857 /* libogg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C933221491A6E50098216A /* libogg.a */; };
+		5B61611B14CCC24C0073B857 /* libvorbis.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C933231491A6E50098216A /* libvorbis.a */; };
+		5B61611C14CCC24C0073B857 /* libvorbisenc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C933241491A6E50098216A /* libvorbisenc.a */; };
+		5B61611D14CCC24C0073B857 /* libvorbisfile.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C933251491A6E50098216A /* libvorbisfile.a */; };
+		5B61611E14CCC24C0073B857 /* libpng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C9332A1491A7390098216A /* libpng.a */; };
+		5B61611F14CCC24C0073B857 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C9332D1491A7810098216A /* libz.dylib */; };
+		5B61612614CCC24C0073B857 /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 42C932ED1491A4CB0098216A /* icon.png */; };
+		5B61612714CCC24C0073B857 /* res in Resources */ = {isa = PBXBuildFile; fileRef = 42C932F21491A53E0098216A /* res */; };
+		5B61612814CCC24C0073B857 /* TEMPLATE_PROJECT-macos.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5B61611214CCC2200073B857 /* TEMPLATE_PROJECT-macos.plist */; };
+		5B61613114CCC33A0073B857 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B61612F14CCC33A0073B857 /* OpenAL.framework */; };
+		5B61613214CCC33A0073B857 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B61613014CCC33A0073B857 /* OpenGLES.framework */; };
+		5B61613414CCC3420073B857 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B61613314CCC3420073B857 /* UIKit.framework */; };
+		5B61613614CCC34A0073B857 /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B61613514CCC3490073B857 /* CoreMotion.framework */; };
+		5B61613814CCC3500073B857 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B61613714CCC3500073B857 /* QuartzCore.framework */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
-		42C932BC1491A0DB0098216A /* TEMPLATE_PROJECT.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TEMPLATE_PROJECT.app"; sourceTree = BUILT_PRODUCTS_DIR; };
-		42C9336B1491AA0E0098216A /* TEMPLATE_PROJECT-macos.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "TEMPLATE_PROJECT-macos.plist"; sourceTree = "<group>"; };
+		42438B521491AD2000D218B8 /* libgameplay.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgameplay.a; path = "~/Library/Developer/Xcode/DerivedData/gameplay-exiunaubxxjndaapmcqkaoeboiob/Build/Products/Debug/libgameplay.a"; sourceTree = "<group>"; };
+		42C932BC1491A0DB0098216A /* TEMPLATE_PROJECT-MacOSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TEMPLATE_PROJECT-MacOSX.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+		42C932C01491A0DB0098216A /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
 		42C932ED1491A4CB0098216A /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = "<group>"; };
-		42C932F21491A53E0098216A /* res */ = {isa = PBXFileReference; lastKnownFileType = folder; path = res; sourceTree = "<group>"; };
 		42C932EF1491A5160098216A /* TemplateGame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TemplateGame.cpp; path = src/TemplateGame.cpp; sourceTree = SOURCE_ROOT; };
 		42C932F01491A5160098216A /* TemplateGame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemplateGame.h; path = src/TemplateGame.h; sourceTree = SOURCE_ROOT; };
-		42C932C01491A0DB0098216A /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
-		42C9331C1491A6750098216A /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+		42C932F21491A53E0098216A /* res */ = {isa = PBXFileReference; lastKnownFileType = folder; path = res; sourceTree = "<group>"; };
 		42C933161491A5EB0098216A /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
+		42C9331C1491A6750098216A /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
 		42C9331E1491A67F0098216A /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; };
-		42438B521491AD2000D218B8 /* libgameplay.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgameplay.a; path = "~/Library/Developer/Xcode/DerivedData/gameplay-exiunaubxxjndaapmcqkaoeboiob/Build/Products/Debug/libgameplay.a"; sourceTree = "<group>"; };
 		42C933201491A6C70098216A /* libbullet.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbullet.a; path = "GAMEPLAY_PATH/external-deps/bullet/lib/macos/libbullet.a"; sourceTree = "<group>"; };
 		42C933221491A6E50098216A /* libogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libogg.a; path = "GAMEPLAY_PATH/external-deps/oggvorbis/lib/macos/libogg.a"; sourceTree = "<group>"; };
 		42C933231491A6E50098216A /* libvorbis.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbis.a; path = "GAMEPLAY_PATH/external-deps/oggvorbis/lib/macos/libvorbis.a"; sourceTree = "<group>"; };
@@ -43,6 +60,14 @@
 		42C933251491A6E50098216A /* libvorbisfile.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisfile.a; path = "GAMEPLAY_PATH/external-deps/oggvorbis/lib/macos/libvorbisfile.a"; sourceTree = "<group>"; };
 		42C9332A1491A7390098216A /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "GAMEPLAY_PATH/external-deps/libpng/lib/macos/libpng.a"; sourceTree = "<group>"; };
 		42C9332D1491A7810098216A /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
+		5B61611214CCC2200073B857 /* TEMPLATE_PROJECT-macos.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "TEMPLATE_PROJECT-macos.plist"; sourceTree = "<group>"; };
+		5B61612C14CCC24C0073B857 /* TEMPLATE_PROJECT-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TEMPLATE_PROJECT-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+		5B61612E14CCC24D0073B857 /* TEMPLATE_PROJECT-ios.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "TEMPLATE_PROJECT-ios.plist"; path = "/Users/bslack/src/git/GamePlay/gameplay-template/TEMPLATE_PROJECT-ios.plist"; sourceTree = "<absolute>"; };
+		5B61612F14CCC33A0073B857 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/OpenAL.framework; sourceTree = DEVELOPER_DIR; };
+		5B61613014CCC33A0073B857 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; };
+		5B61613314CCC3420073B857 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
+		5B61613514CCC3490073B857 /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/CoreMotion.framework; sourceTree = DEVELOPER_DIR; };
+		5B61613714CCC3500073B857 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -65,13 +90,34 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		5B61611714CCC24C0073B857 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				5B61613814CCC3500073B857 /* QuartzCore.framework in Frameworks */,
+				5B61613614CCC34A0073B857 /* CoreMotion.framework in Frameworks */,
+				5B61613414CCC3420073B857 /* UIKit.framework in Frameworks */,
+				5B61613114CCC33A0073B857 /* OpenAL.framework in Frameworks */,
+				5B61613214CCC33A0073B857 /* OpenGLES.framework in Frameworks */,
+				5B61611814CCC24C0073B857 /* libgameplay.a in Frameworks */,
+				5B61611914CCC24C0073B857 /* libbullet.a in Frameworks */,
+				5B61611A14CCC24C0073B857 /* libogg.a in Frameworks */,
+				5B61611B14CCC24C0073B857 /* libvorbis.a in Frameworks */,
+				5B61611C14CCC24C0073B857 /* libvorbisenc.a in Frameworks */,
+				5B61611D14CCC24C0073B857 /* libvorbisfile.a in Frameworks */,
+				5B61611E14CCC24C0073B857 /* libpng.a in Frameworks */,
+				5B61611F14CCC24C0073B857 /* libz.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
 		42C932B11491A0DB0098216A = {
 			isa = PBXGroup;
 			children = (
-				42C9336B1491AA0E0098216A /* TEMPLATE_PROJECT-macos.plist */,
+				5B61611214CCC2200073B857 /* TEMPLATE_PROJECT-macos.plist */,
+				5B61612E14CCC24D0073B857 /* TEMPLATE_PROJECT-ios.plist */,
 				42C932ED1491A4CB0098216A /* icon.png */,
 				42C932F21491A53E0098216A /* res */,
 				42C932C61491A0DB0098216A /* src */,
@@ -84,7 +130,8 @@
 		42C932BD1491A0DB0098216A /* Products */ = {
 			isa = PBXGroup;
 			children = (
-				42C932BC1491A0DB0098216A /* TEMPLATE_PROJECT.app */,
+				42C932BC1491A0DB0098216A /* TEMPLATE_PROJECT-MacOSX.app */,
+				5B61612C14CCC24C0073B857 /* TEMPLATE_PROJECT-iOS.app */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -92,10 +139,8 @@
 		42C932BF1491A0DB0098216A /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
-				42C932C01491A0DB0098216A /* Cocoa.framework */,
-				42C9331C1491A6750098216A /* QuartzCore.framework */,
-				42C933161491A5EB0098216A /* OpenGL.framework */,
-				42C9331E1491A67F0098216A /* OpenAL.framework */,
+				5B61613A14CCC3590073B857 /* Mac OS X */,
+				5B61613914CCC3560073B857 /* iOS */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";
@@ -106,8 +151,7 @@
 				42C932EF1491A5160098216A /* TemplateGame.cpp */,
 				42C932F01491A5160098216A /* TemplateGame.h */,
 			);
-			name = src;
-			path = "src";
+			path = src;
 			sourceTree = "<group>";
 		};
 		42C932DD1491A1050098216A /* Libraries */ = {
@@ -125,12 +169,35 @@
 			name = Libraries;
 			sourceTree = "<group>";
 		};
+		5B61613914CCC3560073B857 /* iOS */ = {
+			isa = PBXGroup;
+			children = (
+				5B61613714CCC3500073B857 /* QuartzCore.framework */,
+				5B61613514CCC3490073B857 /* CoreMotion.framework */,
+				5B61613314CCC3420073B857 /* UIKit.framework */,
+				5B61612F14CCC33A0073B857 /* OpenAL.framework */,
+				5B61613014CCC33A0073B857 /* OpenGLES.framework */,
+			);
+			name = iOS;
+			sourceTree = "<group>";
+		};
+		5B61613A14CCC3590073B857 /* Mac OS X */ = {
+			isa = PBXGroup;
+			children = (
+				42C932C01491A0DB0098216A /* Cocoa.framework */,
+				42C9331C1491A6750098216A /* QuartzCore.framework */,
+				42C933161491A5EB0098216A /* OpenGL.framework */,
+				42C9331E1491A67F0098216A /* OpenAL.framework */,
+			);
+			name = "Mac OS X";
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
-		42C932BB1491A0DB0098216A /* TEMPLATE_PROJECT */ = {
+		42C932BB1491A0DB0098216A /* TEMPLATE_PROJECT-MacOSX */ = {
 			isa = PBXNativeTarget;
-			buildConfigurationList = 42C932DA1491A0DB0098216A /* Build configuration list for PBXNativeTarget "TEMPLATE_PROJECT" */;
+			buildConfigurationList = 42C932DA1491A0DB0098216A /* Build configuration list for PBXNativeTarget "TEMPLATE_PROJECT-MacOSX" */;
 			buildPhases = (
 				42C932B81491A0DB0098216A /* Sources */,
 				42C932B91491A0DB0098216A /* Frameworks */,
@@ -141,9 +208,27 @@
 			);
 			dependencies = (
 			);
-			name = "TEMPLATE_PROJECT";
-			productName = "TEMPLATE_PROJECT";
-			productReference = 42C932BC1491A0DB0098216A /* TEMPLATE_PROJECT.app */;
+			name = "TEMPLATE_PROJECT-MacOSX";
+			productName = TEMPLATE_PROJECT;
+			productReference = 42C932BC1491A0DB0098216A /* TEMPLATE_PROJECT-MacOSX.app */;
+			productType = "com.apple.product-type.application";
+		};
+		5B61611414CCC24C0073B857 /* TEMPLATE_PROJECT-iOS */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 5B61612914CCC24C0073B857 /* Build configuration list for PBXNativeTarget "TEMPLATE_PROJECT-iOS" */;
+			buildPhases = (
+				5B61611514CCC24C0073B857 /* Sources */,
+				5B61611714CCC24C0073B857 /* Frameworks */,
+				5B61612414CCC24C0073B857 /* ShellScript */,
+				5B61612514CCC24C0073B857 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "TEMPLATE_PROJECT-iOS";
+			productName = TEMPLATE_PROJECT;
+			productReference = 5B61612C14CCC24C0073B857 /* TEMPLATE_PROJECT-iOS.app */;
 			productType = "com.apple.product-type.application";
 		};
 /* End PBXNativeTarget section */
@@ -154,7 +239,7 @@
 			attributes = {
 				LastUpgradeCheck = 0420;
 			};
-			buildConfigurationList = 42C932B61491A0DB0098216A /* Build configuration list for PBXProject "TEMPLATE_PROJECT" */;
+			buildConfigurationList = 42C932B61491A0DB0098216A /* Build configuration list for PBXProject "gameplay-template" */;
 			compatibilityVersion = "Xcode 3.2";
 			developmentRegion = English;
 			hasScannedForEncodings = 0;
@@ -166,7 +251,8 @@
 			projectDirPath = "";
 			projectRoot = "";
 			targets = (
-				42C932BB1491A0DB0098216A /* TEMPLATE_PROJECT */,
+				42C932BB1491A0DB0098216A /* TEMPLATE_PROJECT-MacOSX */,
+				5B61611414CCC24C0073B857 /* TEMPLATE_PROJECT-iOS */,
 			);
 		};
 /* End PBXProject section */
@@ -178,6 +264,17 @@
 			files = (
 				42C932EE1491A4CB0098216A /* icon.png in Resources */,
 				42C932F31491A53E0098216A /* res in Resources */,
+				5B61611314CCC2200073B857 /* TEMPLATE_PROJECT-macos.plist in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		5B61612514CCC24C0073B857 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				5B61612614CCC24C0073B857 /* icon.png in Resources */,
+				5B61612714CCC24C0073B857 /* res in Resources */,
+				5B61612814CCC24C0073B857 /* TEMPLATE_PROJECT-macos.plist in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -197,6 +294,19 @@
 			shellPath = /bin/sh;
 			shellScript = "touch -cm ${SRCROOT}/res";
 		};
+		5B61612414CCC24C0073B857 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "touch -cm ${SRCROOT}/res";
+		};
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
@@ -208,6 +318,14 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		5B61611514CCC24C0073B857 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				5B61611614CCC24C0073B857 /* TemplateGame.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXSourcesBuildPhase section */
 
 /* Begin XCBuildConfiguration section */
@@ -265,23 +383,22 @@
 		42C932DB1491A0DB0098216A /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
 				GCC_PRECOMPILE_PREFIX_HEADER = NO;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
 				GCC_WARN_UNUSED_VARIABLE = NO;
 				HEADER_SEARCH_PATHS = (
-					"GAMEPLAY_PATH/gameplay/src",
+					GAMEPLAY_PATH/gameplay/src,
 					"GAMEPLAY_PATH/external-deps/libpng/include",
 					"GAMEPLAY_PATH/external-deps/bullet/include",
 					"GAMEPLAY_PATH/external-deps/oggvorbis/include",
 				);
-				INFOPLIST_FILE = "TEMPLATE_PROJECT-macos.plist";
+				INFOPLIST_FILE = "gameplay-template-macos.plist";
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"GAMEPLAY_PATH/external-deps/libpng/lib/macos\"",
 					"\"GAMEPLAY_PATH/external-deps/bullet/lib/macos\"",
 					"\"GAMEPLAY_PATH/external-deps/oggvorbis/lib/macos\"",
-					"\"~/Library/Developer/Xcode/DerivedData/gameplay-exiunaubxxjndaapmcqkaoeboiob/Build/Products/Debug\"",
 				);
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				USER_HEADER_SEARCH_PATHS = "";
@@ -292,23 +409,22 @@
 		42C932DC1491A0DB0098216A /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
 				GCC_PRECOMPILE_PREFIX_HEADER = NO;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
 				GCC_WARN_UNUSED_VARIABLE = NO;
 				HEADER_SEARCH_PATHS = (
-					"GAMEPLAY_PATH/gameplay/src",
+					GAMEPLAY_PATH/gameplay/src,
 					"GAMEPLAY_PATH/external-deps/libpng/include",
 					"GAMEPLAY_PATH/external-deps/bullet/include",
 					"GAMEPLAY_PATH/external-deps/oggvorbis/include",
 				);
-				INFOPLIST_FILE = "TEMPLATE_PROJECT-macos.plist";
+				INFOPLIST_FILE = "gameplay-template-macos.plist";
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"GAMEPLAY_PATH/external-deps/libpng/lib/macos\"",
 					"\"GAMEPLAY_PATH/external-deps/bullet/lib/macos\"",
 					"\"GAMEPLAY_PATH/external-deps/oggvorbis/lib/macos\"",
-					"\"~/Library/Developer/Xcode/DerivedData/gameplay-exiunaubxxjndaapmcqkaoeboiob/Build/Products/Debug\"",
 				);
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				USER_HEADER_SEARCH_PATHS = "";
@@ -316,10 +432,60 @@
 			};
 			name = Release;
 		};
+		5B61612A14CCC24C0073B857 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_PRECOMPILE_PREFIX_HEADER = NO;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+				GCC_WARN_UNUSED_VARIABLE = NO;
+				HEADER_SEARCH_PATHS = (
+					GAMEPLAY_PATH/gameplay/src,
+					"GAMEPLAY_PATH/external-deps/libpng/include",
+					"GAMEPLAY_PATH/external-deps/bullet/include",
+					"GAMEPLAY_PATH/external-deps/oggvorbis/include",
+				);
+				INFOPLIST_FILE = "gameplay-template-ios.plist";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"GAMEPLAY_PATH/external-deps/libpng/lib/ios/$(CURRENT_ARCH)\"",
+					"\"GAMEPLAY_PATH/external-deps/bullet/lib/ios/$(CURRENT_ARCH)\"",
+					"\"GAMEPLAY_PATH/external-deps/oggvorbis/lib/ios/$(CURRENT_ARCH)\"",
+				);
+				SDKROOT = iphoneos;
+				USER_HEADER_SEARCH_PATHS = "";
+				WRAPPER_EXTENSION = app;
+			};
+			name = Debug;
+		};
+		5B61612B14CCC24C0073B857 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_PRECOMPILE_PREFIX_HEADER = NO;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+				GCC_WARN_UNUSED_VARIABLE = NO;
+				HEADER_SEARCH_PATHS = (
+					GAMEPLAY_PATH/gameplay/src,
+					"GAMEPLAY_PATH/external-deps/libpng/include",
+					"GAMEPLAY_PATH/external-deps/bullet/include",
+					"GAMEPLAY_PATH/external-deps/oggvorbis/include",
+				);
+				INFOPLIST_FILE = "gameplay-template-ios.plist";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"GAMEPLAY_PATH/external-deps/libpng/lib/ios/$(CURRENT_ARCH)\"",
+					"\"GAMEPLAY_PATH/external-deps/bullet/lib/ios/$(CURRENT_ARCH)\"",
+					"\"GAMEPLAY_PATH/external-deps/oggvorbis/lib/ios/$(CURRENT_ARCH)\"",
+				);
+				SDKROOT = iphoneos;
+				USER_HEADER_SEARCH_PATHS = "";
+				WRAPPER_EXTENSION = app;
+			};
+			name = Release;
+		};
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
-		42C932B61491A0DB0098216A /* Build configuration list for PBXProject "TEMPLATE_PROJECT" */ = {
+		42C932B61491A0DB0098216A /* Build configuration list for PBXProject "gameplay-template" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
 				42C932D81491A0DB0098216A /* Debug */,
@@ -328,7 +494,7 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
-		42C932DA1491A0DB0098216A /* Build configuration list for PBXNativeTarget "TEMPLATE_PROJECT" */ = {
+		42C932DA1491A0DB0098216A /* Build configuration list for PBXNativeTarget "TEMPLATE_PROJECT-MacOSX" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
 				42C932DB1491A0DB0098216A /* Debug */,
@@ -337,6 +503,15 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		5B61612914CCC24C0073B857 /* Build configuration list for PBXNativeTarget "TEMPLATE_PROJECT-iOS" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				5B61612A14CCC24C0073B857 /* Debug */,
+				5B61612B14CCC24C0073B857 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 /* End XCConfigurationList section */
 	};
 	rootObject = 42C932B31491A0DB0098216A /* Project object */;

+ 2 - 2
gameplay.doxyfile

@@ -26,7 +26,7 @@ DOXYFILE_ENCODING      = UTF-8
 # identify the project. Note that if you do not use Doxywizard you need 
 # to put quotes around the project name if it contains spaces.
 
-PROJECT_NAME           = GamePlay
+PROJECT_NAME           = gameplay
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number. 
 # This could be handy for archiving the generated documentation or 
@@ -45,7 +45,7 @@ PROJECT_BRIEF          =
 # exceed 55 pixels and the maximum width should not exceed 200 pixels. 
 # Doxygen will copy the logo to the output directory.
 
-PROJECT_LOGO           = C:/Code/GamePlay/gameplay-logo.png
+PROJECT_LOGO           = 
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
 # base path where the generated documentation will be put. 

+ 72 - 69
gameplay/src/AudioController.cpp

@@ -56,49 +56,49 @@ void AudioController::initialize()
 #else
     // Create the engine.
     SLresult result = slCreateEngine(&_engineObject, 0, NULL, 0, NULL, NULL);
-    if (result != SL_RESULT_SUCCESS)
-    {
-        LOG_ERROR("AudioController::initialize() error. Unable to create OpenSL engine.");
-        return;
-    }
-
-    // Realize the engine.
-    result = (*_engineObject)->Realize(_engineObject, SL_BOOLEAN_FALSE);
-    if (result != SL_RESULT_SUCCESS)
-    {
-        LOG_ERROR("AudioController::initialize() error. Unable to realize OpenSL engine.");
-        return;
-    }
-
-    // Get the engine interface in order to create other objects later on.
-    result = (*_engineObject)->GetInterface(_engineObject, SL_IID_ENGINE, &_engineEngine);
-    if (result != SL_RESULT_SUCCESS)
-    {
-        LOG_ERROR("AudioController::initialize() error. Unable to retrieve OpenSL engine interface.");
-        return;
-    }
-
-    // Create the output mix.
-    result = (*_engineEngine)->CreateOutputMix(_engineEngine, &_outputMixObject, 0, NULL, NULL);
-    if (result != SL_RESULT_SUCCESS)
-    {
-        LOG_ERROR("AudioController::initialize() error. Unable to create OpenSL output mix.");
-        return;
-    }
-
-    // Realize the output mix.
-    result = (*_outputMixObject)->Realize(_outputMixObject, SL_BOOLEAN_FALSE);
-    if (result != SL_RESULT_SUCCESS)
-    {
-        LOG_ERROR("AudioController::initialize() error. Unable to realize OpenSL output mix.");
-        return;
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to create OpenSL engine.");
+        return;
+    }
+
+    // Realize the engine.
+    result = (*_engineObject)->Realize(_engineObject, SL_BOOLEAN_FALSE);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to realize OpenSL engine.");
+        return;
+    }
+
+    // Get the engine interface in order to create other objects later on.
+    result = (*_engineObject)->GetInterface(_engineObject, SL_IID_ENGINE, &_engineEngine);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to retrieve OpenSL engine interface.");
+        return;
+    }
+
+    // Create the output mix.
+    result = (*_engineEngine)->CreateOutputMix(_engineEngine, &_outputMixObject, 0, NULL, NULL);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to create OpenSL output mix.");
+        return;
+    }
+
+    // Realize the output mix.
+    result = (*_outputMixObject)->Realize(_outputMixObject, SL_BOOLEAN_FALSE);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to realize OpenSL output mix.");
+        return;
     }
 #endif
 }
 
 void AudioController::finalize()
 {
-#ifndef __ANDROID__
+#ifndef __ANDROID__
     alcMakeContextCurrent(NULL);
     if (_alcContext)
     {
@@ -111,17 +111,17 @@ void AudioController::finalize()
         _alcDevice = NULL;
     }
 #else
-    if (_outputMixObject != NULL)
-    {
-        (*_outputMixObject)->Destroy(_outputMixObject);
-        _outputMixObject = NULL;
-    }
-
-    if (_engineObject != NULL)
-    {
-        (*_engineObject)->Destroy(_engineObject);
-        _engineObject = NULL;
-        _engineEngine = NULL;
+    if (_outputMixObject != NULL)
+    {
+        (*_outputMixObject)->Destroy(_outputMixObject);
+        _outputMixObject = NULL;
+    }
+
+    if (_engineObject != NULL)
+    {
+        (*_engineObject)->Destroy(_engineObject);
+        _engineObject = NULL;
+        _engineEngine = NULL;
     }
 #endif
 }
@@ -145,6 +145,9 @@ void AudioController::pause()
 
 void AudioController::resume()
 {
+#ifndef __ANDROID__    
+    alcMakeContextCurrent(_alcContext);
+#endif
     std::list<AudioSource*>::iterator itr = _playingSources.begin();
 
     // For each source that is playing, resume it.
@@ -173,7 +176,7 @@ void AudioController::update(long elapsedTime)
 #else
         if (!_listenerObject)
         {
-            const SLInterfaceID interfaces[3] = {SL_IID_3DDOPPLER, SL_IID_3DLOCATION};
+            const SLInterfaceID interfaces[3] = {SL_IID_3DDOPPLER, SL_IID_3DLOCATION};
             const SLboolean required[3] = {SL_BOOLEAN_FALSE, SL_BOOLEAN_FALSE};
             SLresult result = (*_engineEngine)->CreateListener(_engineEngine, &_listenerObject, 2, interfaces, required);
             if (result != SL_RESULT_SUCCESS)
@@ -189,20 +192,20 @@ void AudioController::update(long elapsedTime)
                 return;
             }
 
-            // Get the doppler interface in order to set the listener's velocity.
-            result = (*_listenerObject)->GetInterface(_listenerObject, SL_IID_3DDOPPLER, &_listenerDoppler);
-            if (result != SL_RESULT_SUCCESS)
-            {
-                WARN("AudioController: Unable to retrieve listener doppler interface.");
-                return;
+            // Get the doppler interface in order to set the listener's velocity.
+            result = (*_listenerObject)->GetInterface(_listenerObject, SL_IID_3DDOPPLER, &_listenerDoppler);
+            if (result != SL_RESULT_SUCCESS)
+            {
+                WARN("AudioController: Unable to retrieve listener doppler interface.");
+                return;
             }
 
             // Get the location interface in order to set the listener's position and orientation.
-            result = (*_listenerObject)->GetInterface(_listenerObject, SL_IID_3DLOCATION, &_listenerLocation);
-            if (result != SL_RESULT_SUCCESS)
-            {
-                WARN("AudioController: Unable to retrieve listener location interface.");
-                return;
+            result = (*_listenerObject)->GetInterface(_listenerObject, SL_IID_3DLOCATION, &_listenerLocation);
+            if (result != SL_RESULT_SUCCESS)
+            {
+                WARN("AudioController: Unable to retrieve listener location interface.");
+                return;
             }
         }
         
@@ -215,9 +218,9 @@ void AudioController::update(long elapsedTime)
         a.y = listener->getOrientationUp().y;
         a.z = listener->getOrientationUp().z;
         SLresult result = (*_listenerLocation)->SetOrientationVectors(_listenerLocation, &f, &a);
-        if (result != SL_RESULT_SUCCESS)
-        {
-            WARN("AudioController: Unable to set listener orientation.");
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioController: Unable to set listener orientation.");
         }
 
         SLVec3D p;
@@ -225,9 +228,9 @@ void AudioController::update(long elapsedTime)
         p.y = listener->getPosition().y;
         p.z = listener->getPosition().z;
         result = (*_listenerLocation)->SetLocationCartesian(_listenerLocation, &p);
-        if (result != SL_RESULT_SUCCESS)
-        {
-            WARN("AudioController: Unable to set listener location.");
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioController: Unable to set listener location.");
         }
 
         SLVec3D v;
@@ -235,9 +238,9 @@ void AudioController::update(long elapsedTime)
         v.y = listener->getVelocity().y;
         v.z = listener->getVelocity().z;
         result = (*_listenerDoppler)->SetVelocityCartesian(_listenerDoppler, &v);
-        if (result != SL_RESULT_SUCCESS)
-        {
-            WARN("AudioController: Unable to set listener velocity.");
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioController: Unable to set listener velocity.");
         }
 #endif
     }

+ 2 - 1
gameplay/src/Game.h

@@ -197,7 +197,8 @@ public:
      * Keyboard callback on keyPress events.
      *
      * @param evt The key event that occured.
-     * @param key The key code that was pressed, released or repeated.
+     * @param key If evt is KEY_PRESS or KEY_RELEASE then key is the key code from Keyboard::Key.
+     *            If evt is KEY_CHAR then key is the unicode value of the character.
      * 
      * @see Keyboard::KeyEvent
      * @see Keyboard::Key

+ 12 - 14
gameplay/src/Keyboard.h

@@ -20,7 +20,8 @@ public:
     enum KeyEvent
     {
         KEY_PRESS,
-        KEY_RELEASE
+        KEY_RELEASE,
+        KEY_CHAR
     };
 
     /**
@@ -40,15 +41,11 @@ public:
         KEY_BACK_TAB          = 0x0089,
         KEY_RETURN            = 0x000D,
         KEY_CAPS_LOCK         = 0x00E5,
-        KEY_LEFT_SHIFT        = 0x00E1,
-        KEY_RIGHT_SHIFT       = 0x00E2,
-        KEY_LEFT_CTRL         = 0x00E3,
-        KEY_RIGHT_CTRL        = 0x00E4,
-        KEY_LEFT_ALT          = 0x00E9,
-        KEY_RIGHT_ALT         = 0x00EA,
+        KEY_SHIFT             = 0x00E1,
+        KEY_CTRL              = 0x00E3,
+        KEY_ALT               = 0x00E9,
         KEY_MENU              = 0x1067,
-        KEY_LEFT_HYPER        = 0x10ED,
-        KEY_RIGHT_HYPER       = 0x10EE,
+        KEY_HYPER             = 0x10ED,
         KEY_INSERT            = 0x1063,
         KEY_HOME              = 0x1050,
         KEY_PG_UP             = 0x1055,
@@ -88,13 +85,13 @@ public:
         KEY_F10               = 0x00C7,
         KEY_F11               = 0x00C8,
         KEY_F12               = 0x00C9,
-        KEY_CIRCUMFLEX        = 0x005E,
         KEY_SPACE             = ' ',
         KEY_EXCLAM            = '!',
         KEY_QUOTE             = '"',
         KEY_NUMBER            = '#',
         KEY_DOLLAR            = '$',
         KEY_PERCENT           = '%',
+        KEY_CIRCUMFLEX        = '^',
         KEY_AMPERSAND         = '&',
         KEY_APOSTROPHE        = '\'',
         KEY_LEFT_PARENTHESIS  = '(',
@@ -183,10 +180,11 @@ public:
         KEY_BAR               = '|',
         KEY_RIGHT_BRACE       = '}',
         KEY_TILDE             = '~',
-        KEY_EURO,
-        KEY_POUND,
-        KEY_YEN,
-        KEY_MIDDLE_DOT
+        KEY_EURO              = 0x20AC,
+        KEY_POUND             = 0x00A3,
+        KEY_YEN               = 0x00A5,
+        KEY_MIDDLE_DOT        = 0x0095,
+        KEY_SEARCH            = 0xFFAA
     };
 
 private:

+ 145 - 17
gameplay/src/PlatformAndroid.cpp

@@ -357,13 +357,11 @@ Keyboard::Key getKey(int keycode, int metastate)
         case AKEYCODE_PERIOD:
             return Keyboard::KEY_PERIOD;
         case AKEYCODE_ALT_LEFT:
-            return Keyboard::KEY_LEFT_ALT;
         case AKEYCODE_ALT_RIGHT:
-            return Keyboard::KEY_RIGHT_ALT;
+            return Keyboard::KEY_ALT;
         case AKEYCODE_SHIFT_LEFT:
-            return Keyboard::KEY_LEFT_SHIFT;
         case AKEYCODE_SHIFT_RIGHT:
-            return Keyboard::KEY_RIGHT_SHIFT;
+            return Keyboard::KEY_SHIFT;
         case AKEYCODE_TAB:
             return Keyboard::KEY_TAB;
         case AKEYCODE_SPACE:
@@ -398,33 +396,161 @@ Keyboard::Key getKey(int keycode, int metastate)
             return Keyboard::KEY_PG_UP;
         case AKEYCODE_PAGE_DOWN:
             return Keyboard::KEY_PG_DOWN;
+        case AKEYCODE_MENU:
+            return Keyboard::KEY_MENU;
+        case AKEYCODE_SEARCH:
+            return Keyboard::KEY_SEARCH;
         default:
             return Keyboard::KEY_NONE;
     }
 }
 
+/**
+ * Returns the unicode value for the given keycode or zero if the key is not a valid printable character.
+ */
+static int getUnicode(int keycode, int metastate)
+{
+    if (keycode == AKEYCODE_DEL)
+        return 0x0008;
+    // TODO: Doesn't support unicode currently.
+    Keyboard::Key key = getKey(keycode, metastate);
+    switch (key)
+    {
+    case Keyboard::KEY_BACKSPACE:
+        return 0x0008;
+    case Keyboard::KEY_TAB:
+        return 0x0009;
+    case Keyboard::KEY_RETURN:
+    case Keyboard::KEY_KP_ENTER:
+        return 0x000A;
+    case Keyboard::KEY_ESCAPE:
+        return 0x001B;
+    case Keyboard::KEY_SPACE:
+    case Keyboard::KEY_EXCLAM:
+    case Keyboard::KEY_QUOTE:
+    case Keyboard::KEY_NUMBER:
+    case Keyboard::KEY_DOLLAR:
+    case Keyboard::KEY_PERCENT:
+    case Keyboard::KEY_CIRCUMFLEX:
+    case Keyboard::KEY_AMPERSAND:
+    case Keyboard::KEY_APOSTROPHE:
+    case Keyboard::KEY_LEFT_PARENTHESIS:
+    case Keyboard::KEY_RIGHT_PARENTHESIS:
+    case Keyboard::KEY_ASTERISK:
+    case Keyboard::KEY_PLUS:
+    case Keyboard::KEY_COMMA:
+    case Keyboard::KEY_MINUS:
+    case Keyboard::KEY_PERIOD:
+    case Keyboard::KEY_SLASH:
+    case Keyboard::KEY_ZERO:
+    case Keyboard::KEY_ONE:
+    case Keyboard::KEY_TWO:
+    case Keyboard::KEY_THREE:
+    case Keyboard::KEY_FOUR:
+    case Keyboard::KEY_FIVE:
+    case Keyboard::KEY_SIX:
+    case Keyboard::KEY_SEVEN:
+    case Keyboard::KEY_EIGHT:
+    case Keyboard::KEY_NINE:
+    case Keyboard::KEY_COLON:
+    case Keyboard::KEY_SEMICOLON:
+    case Keyboard::KEY_LESS_THAN:
+    case Keyboard::KEY_EQUAL:
+    case Keyboard::KEY_GREATER_THAN:
+    case Keyboard::KEY_QUESTION:
+    case Keyboard::KEY_AT:
+    case Keyboard::KEY_CAPITAL_A:
+    case Keyboard::KEY_CAPITAL_B:
+    case Keyboard::KEY_CAPITAL_C:
+    case Keyboard::KEY_CAPITAL_D:
+    case Keyboard::KEY_CAPITAL_E:
+    case Keyboard::KEY_CAPITAL_F:
+    case Keyboard::KEY_CAPITAL_G:
+    case Keyboard::KEY_CAPITAL_H:
+    case Keyboard::KEY_CAPITAL_I:
+    case Keyboard::KEY_CAPITAL_J:
+    case Keyboard::KEY_CAPITAL_K:
+    case Keyboard::KEY_CAPITAL_L:
+    case Keyboard::KEY_CAPITAL_M:
+    case Keyboard::KEY_CAPITAL_N:
+    case Keyboard::KEY_CAPITAL_O:
+    case Keyboard::KEY_CAPITAL_P:
+    case Keyboard::KEY_CAPITAL_Q:
+    case Keyboard::KEY_CAPITAL_R:
+    case Keyboard::KEY_CAPITAL_S:
+    case Keyboard::KEY_CAPITAL_T:
+    case Keyboard::KEY_CAPITAL_U:
+    case Keyboard::KEY_CAPITAL_V:
+    case Keyboard::KEY_CAPITAL_W:
+    case Keyboard::KEY_CAPITAL_X:
+    case Keyboard::KEY_CAPITAL_Y:
+    case Keyboard::KEY_CAPITAL_Z:
+    case Keyboard::KEY_LEFT_BRACKET:
+    case Keyboard::KEY_BACK_SLASH:
+    case Keyboard::KEY_RIGHT_BRACKET:
+    case Keyboard::KEY_UNDERSCORE:
+    case Keyboard::KEY_GRAVE:
+    case Keyboard::KEY_A:
+    case Keyboard::KEY_B:
+    case Keyboard::KEY_C:
+    case Keyboard::KEY_D:
+    case Keyboard::KEY_E:
+    case Keyboard::KEY_F:
+    case Keyboard::KEY_G:
+    case Keyboard::KEY_H:
+    case Keyboard::KEY_I:
+    case Keyboard::KEY_J:
+    case Keyboard::KEY_K:
+    case Keyboard::KEY_L:
+    case Keyboard::KEY_M:
+    case Keyboard::KEY_N:
+    case Keyboard::KEY_O:
+    case Keyboard::KEY_P:
+    case Keyboard::KEY_Q:
+    case Keyboard::KEY_R:
+    case Keyboard::KEY_S:
+    case Keyboard::KEY_T:
+    case Keyboard::KEY_U:
+    case Keyboard::KEY_V:
+    case Keyboard::KEY_W:
+    case Keyboard::KEY_X:
+    case Keyboard::KEY_Y:
+    case Keyboard::KEY_Z:
+    case Keyboard::KEY_LEFT_BRACE:
+    case Keyboard::KEY_BAR:
+    case Keyboard::KEY_RIGHT_BRACE:
+    case Keyboard::KEY_TILDE:
+        return key;
+    default:
+        return 0;
+    }
+}
+
 // Process the next input event.
 static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
 {
     if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION)
     {
         int32_t data = AMotionEvent_getAction(event);
-        int contactIndex = data >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
         Touch::TouchEvent touchEvent;
-        switch (data & AMOTION_EVENT_ACTION_MASK)
+        size_t pointerCount = AMotionEvent_getPointerCount(event);
+        for (size_t i = 0; i < pointerCount; ++i)
         {
-            case AMOTION_EVENT_ACTION_DOWN:
-                touchEvent = Touch::TOUCH_PRESS;
-                break;
-            case AMOTION_EVENT_ACTION_UP:
-                touchEvent = Touch::TOUCH_RELEASE;
-                break;
-            case AMOTION_EVENT_ACTION_MOVE:
-                touchEvent = Touch::TOUCH_MOVE;
-                break;
+            switch (data & AMOTION_EVENT_ACTION_MASK)
+            {
+                case AMOTION_EVENT_ACTION_DOWN:
+                    touchEvent = Touch::TOUCH_PRESS;
+                    break;
+                case AMOTION_EVENT_ACTION_UP:
+                    touchEvent = Touch::TOUCH_RELEASE;
+                    break;
+                case AMOTION_EVENT_ACTION_MOVE:
+                    touchEvent = Touch::TOUCH_MOVE;
+                    break;
+            }
+            size_t pointerId = AMotionEvent_getPointerId(event, i);
+            Game::getInstance()->touchEvent(touchEvent, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), pointerId);
         }
-    
-        Game::getInstance()->touchEvent(touchEvent, AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0), contactIndex);
         return 1;
     } 
     else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY)
@@ -437,6 +563,8 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
         {
             case AKEY_EVENT_ACTION_DOWN:
                 Game::getInstance()->keyEvent(Keyboard::KEY_PRESS, getKey(keycode, metastate));
+                if (int character = getUnicode(keycode, metastate))
+                    Game::getInstance()->keyEvent(Keyboard::KEY_CHAR, character);
                 break;
                     
             case AKEY_EVENT_ACTION_UP:

+ 8 - 8
gameplay/src/PlatformMacOS.mm

@@ -452,28 +452,28 @@ int getKey(unsigned short keyCode, unsigned int modifierFlags)
             _game->keyEvent((flags & NSAlphaShiftKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_CAPS_LOCK);
             break;
         case 0x38:
-            _game->keyEvent((flags & NSShiftKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_LEFT_SHIFT);
+            _game->keyEvent((flags & NSShiftKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_SHIFT);
             break;
         case 0x3C:
-            _game->keyEvent((flags & NSShiftKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_RIGHT_SHIFT);
+            _game->keyEvent((flags & NSShiftKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_SHIFT);
             break;
         case 0x3A:
-            _game->keyEvent((flags & NSAlternateKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_LEFT_ALT);
+            _game->keyEvent((flags & NSAlternateKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_ALT);
             break;
         case 0x3D:
-            _game->keyEvent((flags & NSAlternateKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_RIGHT_ALT);
+            _game->keyEvent((flags & NSAlternateKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_ALT);
             break;
         case 0x3B:
-            _game->keyEvent((flags & NSControlKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_LEFT_CTRL);
+            _game->keyEvent((flags & NSControlKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_CTRL);
             break;
         case 0x3E:
-            _game->keyEvent((flags & NSControlKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_RIGHT_CTRL);
+            _game->keyEvent((flags & NSControlKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_CTRL);
             break;
         case 0x37:
-            _game->keyEvent((flags & NSCommandKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_LEFT_HYPER);
+            _game->keyEvent((flags & NSCommandKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_HYPER);
             break;
         case 0x36:
-            _game->keyEvent((flags & NSCommandKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_RIGHT_HYPER);
+            _game->keyEvent((flags & NSCommandKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_HYPER);
             break;
     }
 }

+ 54 - 9
gameplay/src/PlatformQNX.cpp

@@ -75,21 +75,17 @@ static Keyboard::Key getKey(int qnxKeycode)
     case KEYCODE_CAPS_LOCK:
         return Keyboard::KEY_CAPS_LOCK;
     case KEYCODE_LEFT_SHIFT:
-        return Keyboard::KEY_LEFT_SHIFT;
     case KEYCODE_RIGHT_SHIFT:
-        return Keyboard::KEY_RIGHT_SHIFT;
+        return Keyboard::KEY_SHIFT;
     case KEYCODE_LEFT_CTRL:
-        return Keyboard::KEY_LEFT_CTRL;
     case KEYCODE_RIGHT_CTRL:
-        return Keyboard::KEY_RIGHT_CTRL;
+        return Keyboard::KEY_CTRL;
     case KEYCODE_LEFT_ALT:
-        return Keyboard::KEY_LEFT_ALT;
     case KEYCODE_RIGHT_ALT:
-        return Keyboard::KEY_RIGHT_ALT;
+        return Keyboard::KEY_ALT;
     case KEYCODE_LEFT_HYPER:
-        return Keyboard::KEY_LEFT_HYPER;
     case KEYCODE_RIGHT_HYPER:
-        return Keyboard::KEY_RIGHT_HYPER;
+        return Keyboard::KEY_HYPER;
     case KEYCODE_INSERT:
         return Keyboard::KEY_INSERT;
     case KEYCODE_HOME:
@@ -252,6 +248,14 @@ static Keyboard::Key getKey(int qnxKeycode)
         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:
@@ -361,6 +365,37 @@ static Keyboard::Key getKey(int qnxKeycode)
     }
 }
 
+/**
+ * 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 printError(const char* format, ...)
 {
     va_list argptr;
@@ -859,7 +894,17 @@ int Platform::enterMessagePump()
                         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;
-                        Game::getInstance()->keyEvent(evt, getKey(value));
+                        // Suppress key repeats
+                        if ((flags & KEY_REPEAT) == 0)
+                        {
+                            Game::getInstance()->keyEvent(evt, getKey(value));
+                            if (evt == gameplay::Keyboard::KEY_PRESS && flags & KEY_SYM_VALID)
+                            {
+                                int unicode = getUnicode(value);
+                                if (unicode)
+                                    Game::getInstance()->keyEvent(gameplay::Keyboard::KEY_CHAR, unicode);
+                            }
+                        }
                         break;
                     }
                 }

+ 30 - 19
gameplay/src/PlatformWin32.cpp

@@ -45,22 +45,19 @@ static gameplay::Keyboard::Key getKey(WPARAM win32KeyCode, bool shiftDown)
         return gameplay::Keyboard::KEY_RETURN;
     case VK_CAPITAL:
         return gameplay::Keyboard::KEY_CAPS_LOCK;
-    case VK_LSHIFT:
-        return gameplay::Keyboard::KEY_LEFT_SHIFT;
-    case VK_RSHIFT:
-        return gameplay::Keyboard::KEY_RIGHT_SHIFT;
-    case VK_LCONTROL:
-        return gameplay::Keyboard::KEY_LEFT_CTRL;
-    case VK_RCONTROL:
-        return gameplay::Keyboard::KEY_RIGHT_CTRL;
-    case VK_LMENU:
-        return gameplay::Keyboard::KEY_LEFT_ALT;
-    case VK_RMENU:
-        return gameplay::Keyboard::KEY_RIGHT_ALT;
+    case VK_SHIFT:
+        return gameplay::Keyboard::KEY_SHIFT;
+    case VK_CONTROL:
+        return gameplay::Keyboard::KEY_CTRL;
+    case VK_MENU:
+        return gameplay::Keyboard::KEY_ALT;
+    case VK_APPS:
+        return gameplay::Keyboard::KEY_MENU;
     case VK_LWIN:
-        return gameplay::Keyboard::KEY_LEFT_HYPER;
     case VK_RWIN:
-        return gameplay::Keyboard::KEY_RIGHT_HYPER;
+        return gameplay::Keyboard::KEY_HYPER;
+    case VK_BROWSER_SEARCH:
+        return gameplay::Keyboard::KEY_SEARCH;
     case VK_INSERT:
         return gameplay::Keyboard::KEY_INSERT;
     case VK_HOME:
@@ -172,7 +169,7 @@ static gameplay::Keyboard::Key getKey(WPARAM win32KeyCode, bool shiftDown)
     case VK_OEM_2:
         return shiftDown ? gameplay::Keyboard::KEY_QUESTION : gameplay::Keyboard::KEY_SLASH;
     case VK_OEM_3:
-        return shiftDown ? gameplay::Keyboard::KEY_GRAVE : gameplay::Keyboard::KEY_TILDE;
+        return shiftDown ? gameplay::Keyboard::KEY_TILDE : gameplay::Keyboard::KEY_GRAVE;
     case VK_OEM_4:
         return shiftDown ? gameplay::Keyboard::KEY_LEFT_BRACE : gameplay::Keyboard::KEY_LEFT_BRACKET;
     case VK_OEM_5:
@@ -351,19 +348,33 @@ LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
         break;
 
     case WM_KEYDOWN:
-        if (wParam == VK_LSHIFT || wParam == VK_RSHIFT)
+        if (wParam == VK_SHIFT)
             shiftDown = true;
 
-        gameplay::Game::getInstance()->keyEvent(gameplay::Keyboard::KEY_PRESS, getKey(wParam, shiftDown));
+        // Suppress key repeats
+        if ((lParam & 0x40000000) == 0)
+            gameplay::Game::getInstance()->keyEvent(gameplay::Keyboard::KEY_PRESS, getKey(wParam, shiftDown));
         break;
-
+        
     case WM_KEYUP:
-        if (wParam == VK_LSHIFT || wParam == VK_RSHIFT)
+        if (wParam == VK_SHIFT)
             shiftDown = false;
 
         gameplay::Game::getInstance()->keyEvent(gameplay::Keyboard::KEY_RELEASE, getKey(wParam, shiftDown));
         break;
 
+    case WM_CHAR:
+        // Suppress key repeats
+        if ((lParam & 0x40000000) == 0)
+            gameplay::Game::getInstance()->keyEvent(gameplay::Keyboard::KEY_CHAR, wParam);
+        break;
+
+    case WM_UNICHAR:
+        // Suppress key repeats
+        if ((lParam & 0x40000000) == 0)
+            gameplay::Game::getInstance()->keyEvent(gameplay::Keyboard::KEY_CHAR, wParam);
+        break;
+
     case WM_SETFOCUS:
         break;
 

+ 2 - 0
gameplay/src/PlatformiOS.mm

@@ -236,6 +236,7 @@ int getKey(unichar keyCode);
         displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update:)];
         [displayLink setFrameInterval:swapInterval];
         [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
+        _game->resume();
 		updating = TRUE;
 	}
 }
@@ -244,6 +245,7 @@ int getKey(unichar keyCode);
 {
 	if (updating)
 	{
+        _game->pause();
 		[displayLink invalidate];
         displayLink = nil;
 		updating = FALSE;

+ 8 - 8
gameplay/src/gameplay.dox

@@ -1,8 +1,8 @@
-/** \mainpage GamePlay - 3D Game Framework
+/** \mainpage gameplay - 3D Game Framework
  *
  * \section intro Introduction
  *
- * GamePlay is a cross-platform, C++, 3D gaming framework that includes a runtime library, tools,
+ * The gameplay framework is a cross-platform, C++, 3D game framework that includes a runtime library, tools,
  * and learning content that allows developers to write games for mobile and desktop platforms
  * without worrying about platform details.
  *
@@ -12,12 +12,12 @@
  *
  * \section Project Features
  *
- * The GamePlay C++ runtime library offers a simple, well-defined, 3D gaming framework that's
+ * The gameplay C++ runtime library offers a simple, well-defined, 3D game framework that's
  * designed to get the most out of today's mobile and desktop platforms. Its purpose is to help you
  * create stunning, world-class, games that harness the power and performance of the platform without
  * being concerned about the platform details. This is accomplished through a set of C++ classes that
  * are built on top of the OS, providing access to the hardware, graphics, and audio libraries
- * (including EGL, OpenGL ES 2.0, and OpenAL 1.1). These classes allow you to:
+ * (including OpenGL ES 2.0, and OpenAL 1.1). These classes allow you to:
  *
  * <b>Build your game without worrying about platform details</b>
  * \li Drive your game with application initialization, update, and render callbacks.
@@ -25,15 +25,15 @@
  * \li Manage your game with control over the device's file system.
  *
  * <b>Create game components with ease</b>
- * \li Add visuals with scene, node, camera, light, mesh, texture, sprite, materials, animation, and physics classes.
+ * \li Add visuals with scene, node, camera, lights, mesh, texture, sprite, materials, animation, and physics classes.
  * \li Control and position the game using the viewport, camera, and audio listener.
  * \li Manage fundamental elements such as fonts, colors, and curves.
- * \li Update game data with built-in math classes for vectors, matrices, rays, planes, and their associated operations.
+ * \li Update game data with built-in math classes for vectors, matrices, rays, planes, bounding volumes and their associated operations.
  *
  * <b>Improve your game and learn</b>
- * \li Supports TrueType fonts and the Khronos COLLADA and FBX interchange formats to import and binary encode your 3D game assets.
+ * \li Supports TrueType fonts and the Khronos COLLADA and Autodesk FBX interchange scene formats to import and binary encode your 3D game assets.
  * \li Built-in materials and shaders to enhance your game's rendering.
- * \li Both mobile and desktop platforms are supported for ease of portability.
+ * \li Both mobile and desktop platforms are supported for ease of portability and tooling options.
  * \li Documentation, tutorials, and code samples are provided.
  *
  */