Ver código fonte

Add sensor support. Android lifecycle fixes. Add retina support.

Joachim Meyer 9 anos atrás
pai
commit
a84f334a1f

+ 66 - 28
build/android/TemplateApp/jni/PolycodeTemplateApp.cpp

@@ -7,7 +7,7 @@
 
 
 PolycodeTemplateApp::PolycodeTemplateApp(PolycodeView *view) {
-    core = new POLYCODE_CORE(view, 800,480,false,false, 0,0,60);
+    core = new POLYCODE_CORE(view, 800,480,false,false, 0,0,60, -1, true);
 
     ResourcePool *globalPool = Services()->getResourceManager()->getGlobalPool();
     globalPool->loadResourcesFromFolder("default", true);
@@ -15,11 +15,11 @@ PolycodeTemplateApp::PolycodeTemplateApp(PolycodeView *view) {
 	// Write your code here!
     srand(time(NULL));
     scene = new Scene(Scene::SCENE_2D);
+    //scene->getActiveCamera()->setOrthoSize(1920, 1080);
     scene->useClearColor = true;
     scene->clearColor.setColor(1.0f / (float)(rand() % 5),1.0f / (float)(rand()%5),1.0f / (float)(rand() % 5),1.0f);
 
     test = new ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 0.5, 0.5);
-    scene->addChild(test);
     test->setPositionY(0.2);
     test->setMaterialByName("Unlit");
     test->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "main_icon.png");
@@ -29,6 +29,15 @@ PolycodeTemplateApp::PolycodeTemplateApp(PolycodeView *view) {
 	testLabel->setPositionY(-0.2);
     scene->addChild(testLabel);
 
+    /*ScenePrimitive* box;
+    for(int i = 0; i < 1000; i++){
+        box = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 0.2, 0.2,0.2);
+        box->setMaterialByName("UnlitUntextured");
+        //box->setColor(1.0, 0.0,0.0, 1.0);
+        //box->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "default/default.png");
+        scene->addChild(box);
+    }*/
+
 //    bgSound = new Sound("FightBG.WAV");
 //    bgSound->Play();
 //    bgSound->setPitch(10.0);
@@ -44,40 +53,60 @@ PolycodeTemplateApp::PolycodeTemplateApp(PolycodeView *view) {
 //     sound3 = new Sound("curve_02_c.wav");
 
     //sound2->Play(true);
-  
+    running = 0;
+    rot = Vector3();
+    fps = new SceneLabel("0", 32, "sans", Label::ANTIALIAS_FULL, 0.1);
+    fps->setPosition(-0.6,0.3);
+    scene->addChild(fps);
+    scene->addChild(test);
+
     Services()->getInput()->addEventListener(this, InputEvent::EVENT_KEYDOWN);
     Services()->getInput()->addEventListener(this, InputEvent::EVENT_TOUCHES_BEGAN);
     Services()->getInput()->addEventListener(this, InputEvent::EVENT_TOUCHES_ENDED);
     Services()->getInput()->addEventListener(this, InputEvent::EVENT_TOUCHES_MOVED);
-    
+    Services()->getCore()->addEventListener(this, Core::EVENT_ACCELEROMETER_MOTION);
+    Services()->getCore()->addEventListener(this, Core::EVENT_GYRO_ROTATION);
 }
 
 void PolycodeTemplateApp::handleEvent(Event *event) {
-    InputEvent *inputEvent = (InputEvent*) event;
-    if(inputEvent->getEventCode() == InputEvent::EVENT_KEYDOWN){
-    switch(inputEvent->getKey()) {
-        case KEY_z:
-            sound1->Play(true);
-        break;
-        case KEY_x:
-            sound2->Play();
-        break;
-        case KEY_c:
-            sound3->Play();
-        break;
+    if(event->getEventType()=="InputEvent"){
+        InputEvent *inputEvent = (InputEvent*) event;
+        if(inputEvent->getEventCode() == InputEvent::EVENT_KEYDOWN){
+        switch(inputEvent->getKey()) {
+            case KEY_z:
+                sound1->Play(true);
+            break;
+            case KEY_x:
+                sound2->Play();
+            break;
+            case KEY_c:
+                sound3->Play();
+            break;
+            }
+        } else if (inputEvent->getEventCode() == InputEvent::EVENT_TOUCHES_BEGAN){
+            //Logger::log("Touch began: %f, %f", inputEvent->touch.position.x, inputEvent->touch.position.y);
+            Ray r = scene->projectRayFromCameraAndViewportCoordinate(scene->getActiveCamera(),inputEvent->touch.position);
+            test->setPosition(r.origin.x, r.origin.y);
+        } else if(inputEvent->getEventCode() == InputEvent::EVENT_TOUCHES_ENDED){
+            //Logger::log("Touch ended: %f, %f", inputEvent->touch.position.x, inputEvent->touch.position.y);
+            Ray r = scene->projectRayFromCameraAndViewportCoordinate(scene->getActiveCamera(),inputEvent->touch.position);
+            test->setPosition(r.origin.x, r.origin.y);
+        } else if(inputEvent->getEventCode() == InputEvent::EVENT_TOUCHES_MOVED){
+            Logger::log("Touch moved: %f, %f", inputEvent->touch.position.x, inputEvent->touch.position.y);
+            Ray r = scene->projectRayFromCameraAndViewportCoordinate(scene->getActiveCamera(),inputEvent->touch.position);
+            Logger::log("Origin: %f, %f", r.origin.x, r.origin.y);
+            test->setPosition(r.origin.x, r.origin.y);
+        }
+    } else if(event->getEventType() == "CoreMotionEvent"){
+        CoreMotionEvent* motionEvent = (CoreMotionEvent*)event;
+        if(motionEvent->getEventCode() == Core::EVENT_ACCELEROMETER_MOTION){
+            //Logger::log("Acceleration: %f, %f, %f", motionEvent->amount.x, motionEvent->amount.y, motionEvent->amount.z);
+            //rot += motionEvent->amount;
+            //test->Translate(motionEvent->amount.y*0.01, motionEvent->amount.x*0.01);
+        } else if (motionEvent->getEventCode() == Core::EVENT_GYRO_ROTATION){
+            //Logger::log("Rotation: %f, %f, %f", motionEvent->amount.x, motionEvent->amount.y, motionEvent->amount.z);
+            test->Translate(motionEvent->amount.x*0.01, motionEvent->amount.y*0.01);
         }
-    } else if (inputEvent->getEventCode() == InputEvent::EVENT_TOUCHES_BEGAN){
-        Logger::log("Touch began: %f, %f", inputEvent->touch.position.x, inputEvent->touch.position.y);
-        Ray r = scene->projectRayFromCameraAndViewportCoordinate(scene->getActiveCamera(),inputEvent->touch.position);
-        test->setPosition(r.origin.x, r.origin.y);
-    } else if(inputEvent->getEventCode() == InputEvent::EVENT_TOUCHES_ENDED){
-        Logger::log("Touch ended: %f, %f", inputEvent->touch.position.x, inputEvent->touch.position.y);
-        Ray r = scene->projectRayFromCameraAndViewportCoordinate(scene->getActiveCamera(),inputEvent->touch.position);
-        test->setPosition(r.origin.x, r.origin.y);
-    } else if(inputEvent->getEventCode() == InputEvent::EVENT_TOUCHES_MOVED){
-        Logger::log("Touch moved: %f, %f", inputEvent->touch.position.x, inputEvent->touch.position.y);
-        Ray r = scene->projectRayFromCameraAndViewportCoordinate(scene->getActiveCamera(),inputEvent->touch.position);
-        test->setPosition(r.origin.x, r.origin.y);
     }
 }
 
@@ -87,6 +116,15 @@ PolycodeTemplateApp::~PolycodeTemplateApp() {
 
 bool PolycodeTemplateApp::Update() {
     if (!core->paused) {
+        //Logger::log("update");
+        running += core->getElapsed();
+        if(running >= 1){
+            //core->deviceAttitude.
+            //Logger::log("Orientation: %f, %f, %f", , rot.y, rot.z);
+            fps->setText(String::NumberToString(core->getFPS(),0));
+            //Logger::log("Backing: %f", Services()->getRenderer()->getBackingResolutionScaleX());
+            running = 0;
+        }
         return core->updateAndRender();
     } else {
         usleep(200000);

+ 3 - 0
build/android/TemplateApp/jni/PolycodeTemplateApp.h

@@ -27,4 +27,7 @@ private:
     Scene *scene;
 
     Core *core;
+    Vector3 rot;
+    Number running;
+    SceneLabel* fps;
 };

+ 3 - 0
include/polycode/core/PolyAndroidCore.h

@@ -121,6 +121,9 @@ namespace Polycode {
 		Number getBackingXRes();
 		Number getBackingYRes();
 		
+		void _setAcceleration(const Vector3& acceleration);
+		void _setGyroRotation(const Vector3& rotation);
+		
 		CoreMutex* getEGLMutex();
 		
 		bool recreateContext;

+ 3 - 2
include/polycode/core/PolyCore.h

@@ -94,8 +94,9 @@ namespace Polycode {
 	
 	class CoreMotionEvent : public Event {
 		public:
-			Vector3 amount;
-	};
+			CoreMotionEvent();
+            Vector3 amount;
+    };
 
 	/**
 	* The main core of the framework. The core deals with system-level functions, such as window initialization and OS interaction. Each platform has its own implementation of this base class. NOTE: SOME OF THE FUNCTIONALITY IN THE CORE IS NOT FULLY IMPLEMENTED!!

+ 38 - 3
include/polycode/view/android/PolycodeView.h

@@ -24,13 +24,41 @@
 
 #include "polycode/core/PolyAndroidCore.h"
 #include <android/native_activity.h>
+#include <android/sensor.h>
 #include <android/log.h>
+#include <android/configuration.h>
+
+//Sensor types the NDK supports but are not in the enum of sensor types
+#define ASENSOR_TYPE_ORIENTATION 3
+#define ASENSOR_TYPE_GRAVITY 9
+#define ASENSOR_TYPE_LINEAR_ACCELERATION 10
+#define ASENSOR_TYPE_ROTATION_VECTOR 11
+#define ASENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED 14
+#define ASENSOR_TYPE_GAME_ROTATION_VECTOR 15
+#define ASENSOR_TYPE_GYROSCOPE_UNCALIBRATED 16
+#define ASENSOR_TYPE_SIGNIFICANT_MOTION 17
+#define ASESNOR_TYPE_STEP_DETECTOR 18
+#define ASESNOR_TYPE_STEP_COUNTER 19
+#define ASENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR 20
 
 #define LOGI(text) ((void)__android_log_write(ANDROID_LOG_INFO, "TemplateApp", text))
 #define LOGE(text) ((void)__android_log_write(ANDROID_LOG_ERROR, "TemplateApp", text))
 
 namespace Polycode {
 	
+	enum{
+		// Android lifecycle status flags.  Not app-specific
+		// Set between onResume and onPause
+		APP_STATUS_ACTIVE           = 0x00000001,
+		// Set between onWindowFocusChanged(true) and (false)
+		APP_STATUS_FOCUSED          = 0x00000002,
+		// Set when the app's SurfaceHolder points to a 
+		// valid, nonzero-sized surface
+		APP_STATUS_HAS_REAL_SURFACE  = 0x00000004,
+		// Mask of all app lifecycle status flags
+		APP_STATUS_INTERACTABLE     = 0x00000007
+	};
+	
     class PolycodeView : public PolycodeViewBase {
         public:
 			PolycodeView(ANativeActivity* native, String title);
@@ -41,9 +69,15 @@ namespace Polycode {
 			ANativeActivity* native_activity;
 			ANativeWindow* native_window;
 			AInputQueue* native_input;
+			AConfiguration* native_config;
+			
+			ASensorManager* sensorManager;
+			ASensorEventQueue* sensorQueue;
+			
+			int64_t gyroTimestamp;
 			
-// 			pthread_mutex_t* windowMutex;
-// 			pthread_cond_t* windowCond;
+			unsigned int lifecycleFlags;
+			bool isInteractable();
     };
 }
 
@@ -71,7 +105,8 @@ void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue *queue);
 void onContentRectChanged(ANativeActivity* activity, const ARect *rect);
 void onConfiguartionChanged(ANativeActivity* activity);
 void onLowMemory(ANativeActivity* activity);
-int inputLoop(int fd, int events, void* data);
+static int inputLoop(int fd, int events, void* data);
+static int sensorLoop(int fd, int events, void* data);
 void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize);
 void* startApp(void* data);
 

+ 48 - 15
src/core/PolyAndroidCore.cpp

@@ -38,7 +38,7 @@ using namespace Polycode;
 extern AndroidCore *core;
 
 void AndroidCoreMutex::lock() {
-    pthread_mutex_lock(&pMutex);    
+    pthread_mutex_lock(&pMutex);
 }
 
 void AndroidCoreMutex::unlock() {
@@ -59,14 +59,26 @@ AndroidCore::AndroidCore(PolycodeView *view, int xRes, int yRes, bool fullScreen
 	graphicsInterface = new OpenGLGraphicsInterface();
 	renderer->setGraphicsInterface(this, graphicsInterface);
 	services->setRenderer(renderer);
-	
+
 	context = NULL;
 	surface = NULL;
 	recreateContext = true;
-	setVideoMode(xRes, yRes, fullScreen, vSync, aaLevel, anisotropyLevel, retinaSupport);
-
-	//services->getSoundManager()->setAudioInterface(new OpenSLAudioInterface());
 	
+	//scale needs to be set now so that labels are scaled correctly	
+	if(retinaSupport){
+		float scale = 1.0;
+		int dens = AConfiguration_getDensity(view->native_config);
+		if(dens >=ACONFIGURATION_DENSITY_LOW && dens <= ACONFIGURATION_DENSITY_XXXHIGH){
+			scale = dens / ACONFIGURATION_DENSITY_MEDIUM;
+		}
+		renderer->setBackingResolutionScale(scale, scale);
+	}
+	
+	//DP are the Density Independent Pixels - this is afaik what should be the size this should work with enabled retinaSupport
+	setVideoMode(AConfiguration_getScreenWidthDp(view->native_config), AConfiguration_getScreenHeightDp(view->native_config), fullScreen, vSync, aaLevel, anisotropyLevel, retinaSupport);
+	
+
+// 	services->getSoundManager()->setAudioInterface(new OpenSLAudioInterface());
 	paused = true;
 	
 	initKeyMap();
@@ -81,7 +93,7 @@ AndroidCore::~AndroidCore() {
 
 void AndroidCore::Render() {
 	renderer->beginFrame();
-	services->Render(Polycode::Rectangle(0, 0, xRes, yRes));
+	services->Render(Polycode::Rectangle(0, 0, getBackingXRes(), getBackingYRes()));
 	renderer->endFrame();
 }
 
@@ -155,11 +167,13 @@ bool AndroidCore::systemUpdate() {
 	if (!running) {
 		return false;
 	}
+	
 	doSleep();
-
+	
 	updateCore();
 	checkEvents();
-
+	ALooper_pollAll(0, NULL, NULL, NULL);
+	
 	return running;
 }
 
@@ -240,7 +254,16 @@ void AndroidCore::handleVideoModeChange(VideoModeChangeInfo *modeInfo) {
 	this->aaLevel = modeInfo->aaLevel;
 	this->vSync = modeInfo->vSync;
 	this->anisotropyLevel = modeInfo->anisotropyLevel;
-
+	
+	float scale = 1.0;
+	if(modeInfo->retinaSupport){
+		int dens = AConfiguration_getDensity(view->native_config);
+		if(dens >=ACONFIGURATION_DENSITY_LOW && dens <= ACONFIGURATION_DENSITY_XXXHIGH){
+			scale = dens / ACONFIGURATION_DENSITY_MEDIUM;
+		}
+	}
+	renderer->setBackingResolutionScale(scale, scale);
+	
 	if(!view->native_window){
 		return;
 	}
@@ -291,6 +314,7 @@ void AndroidCore::handleVideoModeChange(VideoModeChangeInfo *modeInfo) {
 		// connect the context to the surface
 		result = eglMakeCurrent(display, surface, surface, context);
 		assert(EGL_FALSE != result);
+		
 		Logger::log("EGL Init finished");
 		
 		recreateContext = false;
@@ -304,10 +328,9 @@ void AndroidCore::flushRenderContext() {
 }
 
 bool AndroidCore::isWindowInitialized(){
-// 	Logger::log("isWindowInitialized");
 	eglMutex->lock();
 // 	Logger::log("locked");
-	if (eglGetCurrentContext() == EGL_NO_CONTEXT || recreateContext){
+	if (eglGetCurrentContext() == EGL_NO_CONTEXT || recreateContext || !view->isInteractable()){
 		eglMutex->unlock();
 		return false;
 	} else {
@@ -326,8 +349,8 @@ void AndroidCore::openURL(String url) {
 
 unsigned int AndroidCore::getTicks() {
 	struct timespec now;
-	clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &now);
-	return now.tv_sec * 1000000L + now.tv_nsec/1000;
+	clock_gettime(CLOCK_MONOTONIC, &now);
+	return now.tv_sec * 1000 + now.tv_nsec/1000000;
 }
 
 String AndroidCore::executeExternalCommand(String command, String args, String inDirectory) {
@@ -368,8 +391,6 @@ void Core::getScreenInfo(int *width, int *height, int *hz) {
 void AndroidCore::setDeviceSize(Number x, Number y) {
 	deviceWidth = x;
 	deviceHeight = y;
-
-	renderer->setBackingResolutionScale(xRes/deviceWidth, yRes/deviceHeight);
 }
 
 Number AndroidCore::getBackingXRes() {
@@ -380,6 +401,18 @@ Number AndroidCore::getBackingYRes() {
 	return deviceHeight;
 }
 
+void AndroidCore::_setAcceleration(const Vector3 &acceleration) {
+    CoreMotionEvent *event = new CoreMotionEvent();
+    event->amount = acceleration;
+    dispatchEvent(event, Core::EVENT_ACCELEROMETER_MOTION);
+}
+
+void AndroidCore::_setGyroRotation(const Vector3 &rotation) {
+    CoreMotionEvent *event = new CoreMotionEvent();
+    event->amount = rotation;
+    dispatchEvent(event, Core::EVENT_GYRO_ROTATION);
+}
+
 void AndroidCore::initKeyMap() {
 	
 	for (int i=0; i<1024; ++i )

+ 4 - 0
src/core/PolyCore.cpp

@@ -402,6 +402,10 @@ namespace Polycode {
 		mutex->unlock();
 	}
 	
+	CoreMotionEvent::CoreMotionEvent(){
+		eventType = "CoreMotionEvent";
+	}	
+
 	DummyCore::DummyCore(): Core(0, 0, false, false, 0, 0, 0, 0) {
 		fileProviders.push_back(new BasicFileProvider());
 	}

+ 5 - 0
src/core/PolyRenderer.cpp

@@ -118,6 +118,11 @@ void RenderThread::updateRenderThread() {
 
 	if (nextFrame) {
 		while (nextFrame->jobQueue.size() > 0) {
+			#if PLATFORM == PLATFORM_ANDROID
+				if(!core->isWindowInitialized()){
+					break;
+				}
+			#endif
 			RendererThreadJob frameJob = nextFrame->jobQueue.front();
 			nextFrame->jobQueue.pop();
 			processJob(frameJob);

+ 99 - 25
src/view/android/PolycodeView.cpp

@@ -51,28 +51,66 @@ PolycodeView::PolycodeView(ANativeActivity* native, String title){
 	native_activity->callbacks->onWindowFocusChanged 	= onWindowFocusChanged;
 	native_activity->callbacks->onInputQueueCreated		= onInputQueueCreated;
 	native_activity->callbacks->onInputQueueDestroyed	= onInputQueueDestroyed;
+	
+	native_config = AConfiguration_new();
+	AConfiguration_fromAssetManager(native_config, native_activity->assetManager);
+// 	AConfiguration* myConfig = AConfiguration_new();
+// 	AConfiguration_copy(myConfig, native_config);
+// 	AConfiguration_setNavHidden(myConfig,ACONFIGURATION_NAVHIDDEN_YES);
+// 	AConfiguration_setKeysHidden(native_config, ACONFIGURATION_KEYSHIDDEN_YES);
+	
+	sensorManager = ASensorManager_getInstance();		
+	
+	const ASensor* accelerometer = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_ACCELEROMETER);
+	const ASensor* gyroscope = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_GYROSCOPE);
+	const ASensor* orientation = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_GAME_ROTATION_VECTOR);
+	
+	ALooper* looper = ALooper_forThread();
+    if(looper == NULL){
+		looper = ALooper_prepare(0);
+	}
+	
+	sensorQueue = ASensorManager_createEventQueue(sensorManager, looper, ALOOPER_POLL_CALLBACK, sensorLoop, this);
+	
+	if(accelerometer){
+// 		Logger::log("Accelerometer found. Name: %s, Vendor: %s", ASensor_getName(accelerometer), ASensor_getVendor(accelerometer));
+		ASensorEventQueue_enableSensor(sensorQueue, accelerometer);
+	}
+	
+	if(gyroscope){
+// 		Logger::log("Gyroscope found. Name: %s, Vendor: %s", ASensor_getName(gyroscope), ASensor_getVendor(gyroscope));
+		ASensorEventQueue_enableSensor(sensorQueue, gyroscope);
+	}
+	
+	if(orientation){
+// 		Logger::log("Orientation found. Name: %s, Vendor: %s", ASensor_getName(orientation), ASensor_getVendor(orientation));
+ 		ASensorEventQueue_enableSensor(sensorQueue, orientation);
+	}
+	gyroTimestamp = 0;
+	
 }
 
-PolycodeView::~PolycodeView(){
-	
+PolycodeView::~PolycodeView(){}
+
+bool PolycodeView::isInteractable(){
+	//Logger::log("isInteractable: %s", ((lifecycleFlags & APP_STATUS_INTERACTABLE) == APP_STATUS_INTERACTABLE) ? "true" : "false");
+	return ((lifecycleFlags & APP_STATUS_INTERACTABLE) == APP_STATUS_INTERACTABLE);
 }
 
 void onStart(ANativeActivity* activity){
 	Logger::log("onStart");
-	if(core)
-	core->paused = false;
 }
 
 void onResume(ANativeActivity* activity){
 	Logger::log("onResume");
 	if(core)
-	core->paused = false;
+		core->paused = false;
+	((PolycodeView*)activity->instance)->lifecycleFlags |= APP_STATUS_ACTIVE;
 }
 
 void onPause(ANativeActivity* activity){
 	Logger::log("onPause");
-	if(core)
-	core->paused = true;
+	((PolycodeView*)activity->instance)->lifecycleFlags &= ~APP_STATUS_ACTIVE;
 }
 
 void* onSaveInstanceState(ANativeActivity* activity, size_t *outSize){
@@ -81,8 +119,6 @@ void* onSaveInstanceState(ANativeActivity* activity, size_t *outSize){
 
 void onStop(ANativeActivity* activity){
 	Logger::log("onStop");
-	if(core)
-	core->paused = true;
 }
 
 void onDestroy(ANativeActivity* activity){
@@ -99,12 +135,14 @@ void onWindowFocusChanged(ANativeActivity* activity, int hasFocus){
 		event.eventCode = Core::EVENT_GAINED_FOCUS;
 		if(core)
 			core->handleSystemEvent(event);
+		((PolycodeView*)activity->instance)->lifecycleFlags|=APP_STATUS_FOCUSED;
 	}else{
 		AndroidEvent event = AndroidEvent();
 		event.eventGroup = AndroidEvent::SYSTEM_FOCUS_EVENT;
 		event.eventCode = Core::EVENT_LOST_FOCUS;
 		if(core)
 			core->handleSystemEvent(event);		
+		((PolycodeView*)activity->instance)->lifecycleFlags&=~APP_STATUS_FOCUSED;
 	}
 }
 
@@ -113,16 +151,13 @@ void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow *window){
 	((PolycodeView*)activity->instance)->native_window = window;
 	int width = ANativeWindow_getWidth(window);
 	int height = ANativeWindow_getHeight(window);
-	if (width < 0)
-		width = 100;
-	if (height < 0)
-		height = 100;
-	if(core){
-		core->recreateContext = true;
- 		core->setDeviceSize(width, height);
-		//Logger::log("Width: %d, Height; %d", width, height);
-		core->getEGLMutex()->unlock();
-		core->setVideoMode(width, height, true, false, core->getAALevel(), 0, false);
+	if (width > 0 && height > 0){
+		((PolycodeView*)activity->instance)->lifecycleFlags|=APP_STATUS_HAS_REAL_SURFACE;
+		if(core){
+			core->recreateContext = true;
+			core->setDeviceSize(width, height);
+			core->setVideoMode(core->getXRes(), core->getYRes(), true, false, core->getAALevel(), 0, true);
+		}
 	}
 }
 
@@ -138,10 +173,9 @@ void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow *window){
 	Logger::log("onNativeWindowDestroyed");
 	((PolycodeView*)activity->instance)->native_window = NULL;
 	if (core){
-		core->getEGLMutex()->lock();
 		core->recreateContext = true;
-		Services()->getRenderer()->getRenderThread()->getFrameInfo();
 	}
+	((PolycodeView*)activity->instance)->lifecycleFlags&=~APP_STATUS_HAS_REAL_SURFACE;
 }
 
 void onInputQueueCreated(ANativeActivity* activity, AInputQueue *queue){
@@ -156,8 +190,8 @@ void onInputQueueCreated(ANativeActivity* activity, AInputQueue *queue){
 
 void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue *queue){
 	Logger::log("onInputQueueDestroyed");
-	((PolycodeView*)activity->instance)->native_input = NULL;
 	AInputQueue_detachLooper(((PolycodeView*)activity->instance)->native_input);
+	((PolycodeView*)activity->instance)->native_input = NULL;
 }
 
 void onContentRectChanged(ANativeActivity* activity, const ARect *rect){
@@ -166,13 +200,14 @@ void onContentRectChanged(ANativeActivity* activity, const ARect *rect){
 
 void onConfiguartionChanged(ANativeActivity* activity){
 	Logger::log("onConfiguartionChanged");
+// 	activity->assetManager
 }
 
 void onLowMemory(ANativeActivity* activity){
 	Logger::log("onLowMemory");
 }
 
-int inputLoop(int fd, int events, void* data){
+static int inputLoop(int fd, int events, void* data){
 	Logger::log("inputLoop");
 	AInputQueue* native_input = ((PolycodeView*)data)->native_input;
 	AndroidEvent event;
@@ -221,7 +256,7 @@ int inputLoop(int fd, int events, void* data){
 							
 							for (int i = 0; i <count; i++){
 								TouchInfo ti;
-								ti.position = Vector2(AMotionEvent_getHistoricalX(aev,i,j), AMotionEvent_getHistoricalY(aev,i,j));
+								ti.position = Vector2(AMotionEvent_getHistoricalX(aev,i,j)/Services()->getRenderer()->getBackingResolutionScaleX(), AMotionEvent_getHistoricalY(aev,i,j)/Services()->getRenderer()->getBackingResolutionScaleY());
 								if(evSource & AINPUT_SOURCE_TOUCHSCREEN){
 									ti.type = TouchInfo::TYPE_TOUCH;
 								} else {
@@ -242,7 +277,8 @@ int inputLoop(int fd, int events, void* data){
 						std::vector<TouchInfo> touches;
 						for (int i = 0; i <count; i++){
 							TouchInfo ti;
-							ti.position = Vector2(AMotionEvent_getX(aev,i), AMotionEvent_getY(aev,i));
+							//TODO: slight offset since retina implementation
+							ti.position = Vector2(AMotionEvent_getX(aev,i)/(core->getBackingXRes()/core->getXRes()), AMotionEvent_getY(aev,i)/(core->getBackingYRes()/core->getYRes()));
 							if(evSource & AINPUT_SOURCE_TOUCHSCREEN){
 								ti.type = TouchInfo::TYPE_TOUCH;
 							} else {
@@ -275,6 +311,44 @@ int inputLoop(int fd, int events, void* data){
 			AInputQueue_finishEvent(native_input, aev, 1);
 		}
 	}
+	return 1;
+}
+
+static int sensorLoop(int fd, int events, void* data){
+// 	Logger::log("sensorLoop");
+	ASensorEventQueue* queue = ((PolycodeView*)data)->sensorQueue;
+	
+	ASensorEvent event;
+	while(ASensorEventQueue_getEvents(queue, &event, 1) > 0){
+// 		Logger::log("event.type: %d", event.type);
+		float dT;
+		switch(event.type){
+			case ASENSOR_TYPE_ACCELEROMETER:
+ 				core->_setAcceleration(Vector3(event.acceleration.x,event.acceleration.y,event.acceleration.z));
+				//Logger::log("event.type: %d", event.type);
+				break;
+			case ASENSOR_TYPE_GYROSCOPE:
+				if(((PolycodeView*)data)->gyroTimestamp!=0){
+					dT = (event.timestamp-((PolycodeView*)data)->gyroTimestamp)/1000000000.0f;
+					core->_setGyroRotation(Vector3(event.vector.x*dT*TODEGREES, event.vector.y*dT*TODEGREES, event.vector.z*dT*TODEGREES));
+					//core->_setGyroRotation(Vector3(TODEGREES*(event.uncalibrated_gyro.x_uncalib - event.uncalibrated_gyro.x_bias), TODEGREES*(event.uncalibrated_gyro.y_uncalib - event.uncalibrated_gyro.y_bias), TODEGREES*(event.uncalibrated_gyro.z_uncalib - event.uncalibrated_gyro.z_bias)));
+					//Logger::log("event.type: %d", event.type);
+				}
+				((PolycodeView*)data)->gyroTimestamp = event.timestamp;
+				break;
+			case ASENSOR_TYPE_GAME_ROTATION_VECTOR:
+				
+//  				Logger::log("event: %f, %f, %f, %f", event.data[3],event.data[0],event.data[1],event.data[2]);
+				//q.fromAngleAxis(acos(event.data[3])*2, Vector3(event.data[0], event.data[1], event.data[2]));
+				Quaternion q=Quaternion(event.data[3],event.data[0],event.data[1],event.data[2]);
+				Vector3 vec = q.toEulerAngles();
+// 				Logger::log("event: %f, %f, %f", vec.x, vec.y, vec.z);
+//  				core->deviceAttitude = q;
+				break;
+		}
+	}
+	
+	return 1;
 }
 
 void ANativeActivity_onCreate(ANativeActivity* activity, void *savedState, size_t savedStateSize) {