ソースを参照

Start on an AndroidCore

First steps towards an AndroidCore.
Joachim Meyer 10 年 前
コミット
697f3d70dc
45 ファイル変更1870 行追加16 行削除
  1. 9 0
      assets/ide/Fonts/Lato-Black.ttf
  2. 1 0
      build/android/.idea/.name
  3. 22 0
      build/android/.idea/compiler.xml
  4. 3 0
      build/android/.idea/copyright/profiles_settings.xml
  5. 20 0
      build/android/.idea/gradle.xml
  6. 46 0
      build/android/.idea/misc.xml
  7. 10 0
      build/android/.idea/modules.xml
  8. 12 0
      build/android/.idea/runConfigurations.xml
  9. 6 0
      build/android/.idea/vcs.xml
  10. 1 0
      build/android/Polycore/.gitignore
  11. 32 0
      build/android/Polycore/AndroidManifest.xml
  12. 46 0
      build/android/Polycore/build.gradle
  13. 7 0
      build/android/Polycore/jni/Android.mk
  14. 4 0
      build/android/Polycore/jni/Application.mk
  15. 17 0
      build/android/Polycore/proguard-rules.pro
  16. 1 0
      build/android/TemplateApp/.gitignore
  17. 36 0
      build/android/TemplateApp/AndroidManifest.xml
  18. 50 0
      build/android/TemplateApp/build.gradle
  19. 37 0
      build/android/TemplateApp/jni/Android.mk
  20. 4 0
      build/android/TemplateApp/jni/Application.mk
  21. 19 0
      build/android/TemplateApp/jni/PolycodeTemplate.cpp
  22. 79 0
      build/android/TemplateApp/jni/PolycodeTemplateApp.cpp
  23. 27 0
      build/android/TemplateApp/jni/PolycodeTemplateApp.h
  24. 17 0
      build/android/TemplateApp/proguard-rules.pro
  25. 13 0
      build/android/TemplateApp/src/main/java/org/polycode/templateapp/PolycodeActivity.java
  26. 23 0
      build/android/build.gradle
  27. 18 0
      build/android/gradle.properties
  28. BIN
      build/android/gradle/wrapper/gradle-wrapper.jar
  29. 6 0
      build/android/gradle/wrapper/gradle-wrapper.properties
  30. 160 0
      build/android/gradlew
  31. 90 0
      build/android/gradlew.bat
  32. 1 0
      build/android/settings.gradle
  33. 2 0
      include/Polycode.h
  34. 64 0
      include/polycode/core/PolyAAssetFileProvider.h
  35. 147 0
      include/polycode/core/PolyAndroidCore.h
  36. 2 2
      include/polycode/core/PolyCore.h
  37. 3 0
      include/polycode/core/PolyGlobals.h
  38. 76 0
      include/polycode/view/android/PolycodeView.h
  39. 118 0
      src/core/PolyAAssetFileProvider.cpp
  40. 367 0
      src/core/PolyAndroidCore.cpp
  41. 8 1
      src/core/PolyLogger.cpp
  42. 1 1
      src/core/PolyMaterialManager.cpp
  43. 7 6
      src/core/PolyOpenGLGraphicsInterface.cpp
  44. 22 6
      src/core/PolyRenderer.cpp
  45. 236 0
      src/view/android/PolycodeView.cpp

+ 9 - 0
assets/ide/Fonts/Lato-Black.ttf

@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+libs

+ 1 - 0
build/android/.idea/.name

@@ -0,0 +1 @@
+Polycore

+ 22 - 0
build/android/.idea/compiler.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <resourceExtensions />
+    <wildcardResourcePatterns>
+      <entry name="!?*.java" />
+      <entry name="!?*.form" />
+      <entry name="!?*.class" />
+      <entry name="!?*.groovy" />
+      <entry name="!?*.scala" />
+      <entry name="!?*.flex" />
+      <entry name="!?*.kt" />
+      <entry name="!?*.clj" />
+      <entry name="!?*.aj" />
+    </wildcardResourcePatterns>
+    <annotationProcessing>
+      <profile default="true" name="Default" enabled="false">
+        <processorPath useClasspath="true" />
+      </profile>
+    </annotationProcessing>
+  </component>
+</project>

+ 3 - 0
build/android/.idea/copyright/profiles_settings.xml

@@ -0,0 +1,3 @@
+<component name="CopyrightManager">
+  <settings default="" />
+</component>

+ 20 - 0
build/android/.idea/gradle.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <option name="distributionType" value="LOCAL" />
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.8" />
+        <option name="gradleJvm" value="1.7" />
+        <option name="modules">
+          <set>
+            <option value="$PROJECT_DIR$" />
+            <option value="$PROJECT_DIR$/Polycore" />
+            <option value="$PROJECT_DIR$/TemplateApp" />
+          </set>
+        </option>
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>

+ 46 - 0
build/android/.idea/misc.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="EntryPointsManager">
+    <entry_points version="2.0" />
+  </component>
+  <component name="NullableNotNullManager">
+    <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
+    <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
+    <option name="myNullables">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
+        </list>
+      </value>
+    </option>
+    <option name="myNotNulls">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+        </list>
+      </value>
+    </option>
+  </component>
+  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
+    <OptionsSetting value="true" id="Add" />
+    <OptionsSetting value="true" id="Remove" />
+    <OptionsSetting value="true" id="Checkout" />
+    <OptionsSetting value="true" id="Update" />
+    <OptionsSetting value="true" id="Status" />
+    <OptionsSetting value="true" id="Edit" />
+    <ConfirmationsSetting value="0" id="Add" />
+    <ConfirmationsSetting value="0" id="Remove" />
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+</project>

+ 10 - 0
build/android/.idea/modules.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/Polycore/Polycore.iml" filepath="$PROJECT_DIR$/Polycore/Polycore.iml" />
+      <module fileurl="file://$PROJECT_DIR$/TemplateApp/TemplateApp.iml" filepath="$PROJECT_DIR$/TemplateApp/TemplateApp.iml" />
+      <module fileurl="file://$PROJECT_DIR$/android.iml" filepath="$PROJECT_DIR$/android.iml" />
+    </modules>
+  </component>
+</project>

+ 12 - 0
build/android/.idea/runConfigurations.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RunConfigurationProducerService">
+    <option name="ignoredProducers">
+      <set>
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+      </set>
+    </option>
+  </component>
+</project>

+ 6 - 0
build/android/.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
+  </component>
+</project>

+ 1 - 0
build/android/Polycore/.gitignore

@@ -0,0 +1 @@
+/build

+ 32 - 0
build/android/Polycore/AndroidManifest.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- BEGIN_INCLUDE(manifest) -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.example.native_activity"
+        android:versionCode="1"
+        android:versionName="1.0">
+
+    <!-- This is the platform API where NativeActivity was introduced. -->
+    <uses-sdk android:minSdkVersion="14" />
+
+    <!-- This .apk has no Java code itself, so set hasCode to false. -->
+    <application android:label="Polycore" android:hasCode="false">
+
+        <!-- Our activity is the built-in NativeActivity framework class.
+             This will take care of integrating with our NDK code. -->
+        <activity android:name="android.app.NativeActivity"
+                android:label="Polycore"
+                android:configChanges="orientation|keyboardHidden">
+            <!-- Tell NativeActivity the name of or .so -->
+            <meta-data android:name="android.app.lib_name"
+                    android:value="native-activity" />
+            <meta-data android:name="android.app.func_name"
+                    android:value="main" />
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest> 
+<!-- END_INCLUDE(manifest) -->

+ 46 - 0
build/android/Polycore/build.gradle

@@ -0,0 +1,46 @@
+import org.apache.tools.ant.taskdefs.condition.Os
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 23
+    buildToolsVersion "23.0.2"
+
+    defaultConfig {
+        applicationId "org.polycode.polycore"
+        minSdkVersion 14
+        targetSdkVersion 23
+        versionCode 1
+        versionName "1.0"
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+
+    sourceSets.main {
+        manifest.srcFile 'AndroidManifest.xml'
+        //jniLibs.srcDir '../../../lib/android/' //set libs as .so's location instead of jniLibs
+        jni.srcDirs = [] //disable automatic ndk-build call with auto-generated Android.mk
+    }
+
+    // call regular ndk-build(.cmd) script from app directory
+    task ndkBuild(type: Exec) {
+        if (Os.isFamily(Os.FAMILY_WINDOWS)) {
+            commandLine 'ndk-build.cmd'
+        } else {
+            commandLine 'ndk-build'
+        }
+    }
+
+    tasks.withType(JavaCompile) {
+        compileTask -> compileTask.dependsOn ndkBuild
+    }
+}
+
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.jar'])
+    testCompile 'junit:junit:4.12'
+    compile 'com.android.support:appcompat-v7:23.1.1'
+}

ファイルの差分が大きいため隠しています
+ 7 - 0
build/android/Polycore/jni/Android.mk


+ 4 - 0
build/android/Polycore/jni/Application.mk

@@ -0,0 +1,4 @@
+APP_PLATFORM := android-14
+APP_ABI := all
+APP_STL := gnustl_static
+APP_CPPFLAGS += -std=c++11

+ 17 - 0
build/android/Polycore/proguard-rules.pro

@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /home/joachim/Android/Sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}

+ 1 - 0
build/android/TemplateApp/.gitignore

@@ -0,0 +1 @@
+/build

+ 36 - 0
build/android/TemplateApp/AndroidManifest.xml

@@ -0,0 +1,36 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.native_activity"
+    android:versionCode="1"
+    android:versionName="1.0">
+
+    <uses-sdk android:minSdkVersion="14" />
+
+    <application android:label="TemplateApp">
+
+
+        <android:uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+        <android:uses-permission android:name="android.permission.READ_PHONE_STATE" />
+        <android:uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
+        <!--
+             Our activity is the built-in NativeActivity framework class.
+             This will take care of integrating with our NDK code.
+        -->
+        <activity
+            android:name="org.polycode.templateapp.PolycodeActivity"
+            android:configChanges="orientation|keyboardHidden"
+            android:label="TemplateApp">
+
+            <!-- Tell NativeActivity the name of our .so -->
+            <meta-data
+                android:name="android.app.lib_name"
+                android:value="TemplateApp" />
+
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest> <!-- END_INCLUDE(manifest) -->

+ 50 - 0
build/android/TemplateApp/build.gradle

@@ -0,0 +1,50 @@
+import org.apache.tools.ant.taskdefs.condition.Os
+
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 23
+    buildToolsVersion "23.0.2"
+
+    defaultConfig {
+        applicationId "org.polycode.templateapp"
+        minSdkVersion 14
+        targetSdkVersion 23
+        versionCode 1
+        versionName "1.0"
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+        debug{
+            jniDebuggable = true
+        }
+    }
+
+    sourceSets.main {
+        manifest.srcFile 'AndroidManifest.xml'
+        jniLibs.srcDir 'libs' //set libs as .so's location instead of jniLibs
+        jni.srcDirs = [] //disable automatic ndk-build call with auto-generated Android.mk
+    }
+
+    // call regular ndk-build(.cmd) script from app directory
+    task ndkBuild(type: Exec) {
+        if (Os.isFamily(Os.FAMILY_WINDOWS)) {
+            commandLine 'ndk-build.cmd'
+        } else {
+            commandLine 'ndk-build'
+        }
+    }
+
+    tasks.withType(JavaCompile) {
+        compileTask -> compileTask.dependsOn ndkBuild
+    }
+}
+
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.jar'])
+    testCompile 'junit:junit:4.12'
+    compile 'com.android.support:appcompat-v7:23.1.1'
+}

+ 37 - 0
build/android/TemplateApp/jni/Android.mk

@@ -0,0 +1,37 @@
+LOCAL_PATH := $(call my-dir)
+SRCDIR := ../../../../src
+LIBDIR := ../../../../lib/android/$(TARGET_ARCH_ABI)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := Polycore
+LOCAL_SRC_FILES := ../../Polycore/obj/local/$(TARGET_ARCH_ABI)/libPolycore.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := freetype
+LOCAL_SRC_FILES := $(LIBDIR)/libfreetype.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libpng
+LOCAL_SRC_FILES := $(LIBDIR)/libpng.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := ogg
+LOCAL_SRC_FILES := $(LIBDIR)/libogg.so
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := vorbis
+LOCAL_SRC_FILES := $(LIBDIR)/libvorbis.so
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := TemplateApp
+LOCAL_LDLIBS := -landroid -lEGL -lGLESv2 -lz -llog
+LOCAL_STATIC_LIBRARIES := Polycore freetype libpng
+LOCAL_SHARED_LIBRARIES := ogg vorbis
+LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../include -DUSE_EGL -DSTRICT_OPENGLES2
+LOCAL_SRC_FILES := PolycodeTemplate.cpp PolycodeTemplateApp.cpp
+include $(BUILD_SHARED_LIBRARY)

+ 4 - 0
build/android/TemplateApp/jni/Application.mk

@@ -0,0 +1,4 @@
+APP_PLATFORM := android-14
+APP_ABI := all
+APP_STL := gnustl_static
+APP_CPPFLAGS += -std=c++11

+ 19 - 0
build/android/TemplateApp/jni/PolycodeTemplate.cpp

@@ -0,0 +1,19 @@
+#include "PolycodeTemplateApp.h"
+#include "polycode/view/android/PolycodeView.h"
+//#include <android_native_app_glue.h>
+
+void android_main(struct startHelper* helper){
+	LOGI("Starting");
+	PolycodeView *view = new PolycodeView(helper->activity, "TemplateApp");
+
+	PolycodeTemplateApp *app = new PolycodeTemplateApp(view);
+
+	pthread_mutex_lock(&helper->mutex);
+    helper->running = 1;
+    pthread_cond_broadcast(&helper->cond);
+    pthread_mutex_unlock(&helper->mutex);
+
+	while(app->Update()) {
+	}
+	return;
+}

+ 79 - 0
build/android/TemplateApp/jni/PolycodeTemplateApp.cpp

@@ -0,0 +1,79 @@
+//
+// Polycode template. Write your code here.
+// 
+
+#include "PolycodeTemplateApp.h"
+#include "polycode/view/android/PolycodeView.h"
+
+
+PolycodeTemplateApp::PolycodeTemplateApp(PolycodeView *view) {
+    core = new POLYCODE_CORE(view, 800,480,false,false, 0,0,60);
+
+    core->addFileSource("android", "default");
+    ResourcePool *globalPool = Services()->getResourceManager()->getGlobalPool();
+    globalPool->loadResourcesFromFolder("default", true);
+
+	// Write your code here!
+    
+    Scene *scene = new Scene(Scene::SCENE_2D);
+    scene->useClearColor = true;
+    scene->clearColor.setColor(1.0f,1.0f,0.13f,1.0f);
+
+    ScenePrimitive *test = new ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 2, 2);
+    scene->addChild(test);
+    test->setColor(1.0,0.0,0.0,1.0);
+	test->setPositionY(0.2);
+    LOGI("scene prim worked");
+
+    SceneLabel *testLabel = new SceneLabel("Hello Polycode!", 32, "sans", Label::ANTIALIAS_FULL, 0.2);
+	testLabel->setPositionY(-0.2);
+    scene->addChild(testLabel);
+/*
+    bgSound = new Sound("bedlayer_main.wav");
+    bgSound->Play();
+//    bgSound->setPitch(10.0);
+    
+    
+    sound1 = new Sound("marimba-lo.wav");
+    
+    sound1->setPitch(2.3);
+    
+    sound2 = new Sound("initial_touch_01.wav");
+    sound3 = new Sound("curve_02_c.wav");
+    
+    //sound2->Play(true);
+  */
+  
+    Services()->getInput()->addEventListener(this, InputEvent::EVENT_KEYDOWN);
+}
+
+void PolycodeTemplateApp::handleEvent(Event *event) {
+    InputEvent *inputEvent = (InputEvent*) event;
+    
+    switch(inputEvent->getKey()) {
+        case KEY_z:
+            sound1->Play(true);
+        break;
+        case KEY_x:
+            sound2->Play();
+        break;
+        case KEY_c:
+            sound3->Play();
+        break;
+            
+    }
+}
+
+PolycodeTemplateApp::~PolycodeTemplateApp() {
+    
+}
+
+bool PolycodeTemplateApp::Update() {
+    if (!core->paused) {
+        //LOGI("Update");
+        return core->updateAndRender();
+    } else {
+        usleep(200*1000);
+        return true;
+    }
+}

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

@@ -0,0 +1,27 @@
+//
+// Polycode template. Write your code here.
+//
+
+#include "Polycode.h"
+
+using namespace Polycode;
+
+class PolycodeTemplateApp : public EventHandler {
+public:
+    PolycodeTemplateApp(PolycodeView *view);
+    ~PolycodeTemplateApp();
+    
+    void handleEvent(Event *event);
+    
+    bool Update();
+    
+private:
+    
+    Sound *bgSound;
+    
+    Sound *sound1;
+    Sound *sound2;
+    Sound *sound3;
+    
+    Core *core;
+};

+ 17 - 0
build/android/TemplateApp/proguard-rules.pro

@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /home/joachim/Android/Sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}

+ 13 - 0
build/android/TemplateApp/src/main/java/org/polycode/templateapp/PolycodeActivity.java

@@ -0,0 +1,13 @@
+package org.polycode.templateapp;
+
+import android.app.NativeActivity;
+
+/**
+ * Created by joachim on 29.02.16.
+ */
+public class PolycodeActivity extends NativeActivity {
+    static {
+        System.loadLibrary("ogg");
+        System.loadLibrary("vorbis");
+    }
+}

+ 23 - 0
build/android/build.gradle

@@ -0,0 +1,23 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    repositories {
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:1.5.0'
+
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        jcenter()
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}

+ 18 - 0
build/android/gradle.properties

@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true

BIN
build/android/gradle/wrapper/gradle-wrapper.jar


+ 6 - 0
build/android/gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,6 @@
+#Wed Oct 21 11:34:03 PDT 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip

+ 160 - 0
build/android/gradlew

@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

+ 90 - 0
build/android/gradlew.bat

@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

+ 1 - 0
build/android/settings.gradle

@@ -0,0 +1 @@
+include ':Polycore', ':TemplateApp'

+ 2 - 0
include/Polycode.h

@@ -103,6 +103,8 @@
 		#else
 		#else
 			#ifdef RPI_CORE
 			#ifdef RPI_CORE
 				#include "polycode/core/PolyRPICore.h"
 				#include "polycode/core/PolyRPICore.h"
+			#elif defined(__ANDROID__)
+				#include "polycode/core/PolyAndroidCore.h"
 			#else
 			#else
 				#ifdef EMSCRIPTEN
 				#ifdef EMSCRIPTEN
 					#include "polycode/core/PolyEmscriptenCore.h"
 					#include "polycode/core/PolyEmscriptenCore.h"

+ 64 - 0
include/polycode/core/PolyAAssetFileProvider.h

@@ -0,0 +1,64 @@
+/*
+ Copyright (C) 2016 by Joachim Meyer
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+#pragma once
+
+#include "polycode/core/PolyCoreFileProvider.h"
+#include <android/asset_manager.h>
+
+namespace Polycode {
+    
+    class _PolyExport AAssetFile : public CoreFile {
+    public:
+        
+        long read( void * ptr, size_t size, size_t count);
+        long write( const void * ptr, size_t size, size_t count);
+        int seek(long int offset, int origin);
+        long tell();
+        
+        AAsset *file;
+    };
+    
+	class _PolyExport AAssetDirClass : public PolyBase {
+	public:
+		AAssetDir* system;
+		String name;
+	};
+	
+    class _PolyExport AAssetFileProvider : public CoreFileProvider {
+        public:
+            AAssetFileProvider(AAssetManager *manager);
+            
+			Polycode::CoreFile *openFile(const String &fileName, const String &opts);
+            void closeFile(Polycode::CoreFile *file);
+            
+			virtual bool parseFolder(const Polycode::String& pathString, bool showHidden, std::vector<OSFileEntry> &targetVector);
+			
+			void addSource(const String &source);
+            void removeSource(const String &source);
+      
+            std::vector<AAssetDirClass> sourceFolders;
+			
+			AAssetManager* manager;
+    };
+    
+}

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

@@ -0,0 +1,147 @@
+/*
+ Copyright (C) 2016 by Joachim Meyer
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <stdio.h>
+#include <assert.h>
+#include <math.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+
+#include <android/native_activity.h>
+
+#include "polycode/core/PolyGlobals.h"
+#include "polycode/core/PolyCore.h"
+#include "polycode/core/PolyInputEvent.h"
+
+#define POLYCODE_CORE AndroidCore
+
+namespace Polycode {
+
+	class PolycodeView;
+// 	class ANativeActivity;
+	
+	class AndroidEvent {
+	public:
+		int eventGroup;
+		int eventCode;
+
+		int mouseX;
+		int mouseY;
+
+		std::vector<TouchInfo> touches;
+		TouchInfo touch;
+
+		PolyKEY keyCode;
+		wchar_t unicodeChar;
+
+		char mouseButton;
+		long eventTime;
+
+		static const int EVENTBASE_PLATFORMEVENT = 0x300;
+		static const int INPUT_EVENT = EVENTBASE_PLATFORMEVENT + 0;
+		static const int SYSTEM_FOCUS_EVENT = EVENTBASE_PLATFORMEVENT + 1;
+	};
+
+
+	class AndroidCoreMutex : public CoreMutex {
+	public:
+		void lock();
+		void unlock();
+		pthread_mutex_t pMutex;
+	};
+
+	class OpenGLGraphicsInterface;
+
+	class _PolyExport AndroidCore : public Core {
+	public:
+
+		AndroidCore(PolycodeView *view, int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel, int frameRate, int monitorIndex = -1, bool retinaSupport = false);
+		~AndroidCore();
+
+		void Render();
+		bool systemUpdate();
+		
+		void setCursor(int cursorType);
+		
+		void createThread(Threaded *target);
+		CoreMutex *createMutex();
+				
+		void copyStringToClipboard(const String& str);
+		String getClipboardString();
+		
+		void createFolder(const String& folderPath);
+		void copyDiskItem(const String& itemPath, const String& destItemPath);
+		void moveDiskItem(const String& itemPath, const String& destItemPath);
+		void removeDiskItem(const String& itemPath);
+		
+		String openFolderPicker();
+		std::vector<String> openFilePicker(std::vector<CoreFileExtension> extensions, bool allowMultiple);
+		String saveFilePicker(std::vector<CoreFileExtension> extensions);
+		
+		void handleVideoModeChange(VideoModeChangeInfo *modeInfo);
+		void flushRenderContext();
+		bool isWindowInitialized();
+		
+		void openURL(String url);
+		
+		unsigned int getTicks();
+		
+		String executeExternalCommand(String command, String args, String inDirectory);
+		bool systemParseFolder(const Polycode::String& pathString, bool showHidden, std::vector<OSFileEntry> &targetVector);
+
+		void handleSystemEvent(AndroidEvent systemEvent);
+		void checkEvents();
+		
+		void setDeviceSize(Number x, Number y);
+
+		Number getBackingXRes();
+		Number getBackingYRes();
+		
+		bool recreateContext;
+	private:
+
+		PolycodeView* view;
+		
+		Number deviceWidth;
+		Number deviceHeight;
+
+		int lastMouseY;
+		int lastMouseX;
+
+		EGLDisplay display;
+		EGLSurface surface;
+		EGLContext context;
+		
+		CoreMutex* eglMutex;
+
+		std::vector<AndroidEvent> systemInputEvents;
+
+		double pcFreq;
+
+		OpenGLGraphicsInterface *graphicsInterface;
+
+	};
+}

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

@@ -307,8 +307,8 @@ namespace Polycode {
 
 
 		virtual void handleVideoModeChange(VideoModeChangeInfo *modeInfo) = 0;
 		virtual void handleVideoModeChange(VideoModeChangeInfo *modeInfo) = 0;
 		virtual void flushRenderContext() = 0;
 		virtual void flushRenderContext() = 0;
-		virtual void prepareRenderContext() {}
-		
+        virtual void prepareRenderContext() {}
+        virtual bool isWindowInitialized() = 0;
 		CoreFile *openFile(const Polycode::String& fileName, const Polycode::String& opts);
 		CoreFile *openFile(const Polycode::String& fileName, const Polycode::String& opts);
 		void closeFile(CoreFile *file);
 		void closeFile(CoreFile *file);
 		
 		

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

@@ -69,6 +69,7 @@ typedef unsigned int PolyRendererIndexType;
 #define PLATFORM_MAC	  2
 #define PLATFORM_MAC	  2
 #define PLATFORM_UNIX	  3
 #define PLATFORM_UNIX	  3
 #define PLATFORM_IOS	  4
 #define PLATFORM_IOS	  4
+#define PLATFORM_ANDROID  5
 
 
 #if defined(_WINDOWS) || defined(WINAPI_FAMILY)	 || defined(WIN32)
 #if defined(_WINDOWS) || defined(WINAPI_FAMILY)	 || defined(WIN32)
 	#define PLATFORM PLATFORM_WINDOWS
 	#define PLATFORM PLATFORM_WINDOWS
@@ -82,6 +83,8 @@ typedef unsigned int PolyRendererIndexType;
 	#else
 	#else
 		#define PLATFORM PLATFORM_MAC
 		#define PLATFORM PLATFORM_MAC
 	#endif
 	#endif
+#elif defined(__ANDROID__)
+	#define PLATFORM PLATFORM_ANDROID
 #else
 #else
 	#include <cstddef>
 	#include <cstddef>
 	#define PLATFORM PLATFORM_UNIX
 	#define PLATFORM PLATFORM_UNIX

+ 76 - 0
include/polycode/view/android/PolycodeView.h

@@ -0,0 +1,76 @@
+/*
+ Copyright (C) 2016 by Joachim Meyer
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+#pragma once
+
+#include "polycode/core/PolyAndroidCore.h"
+#include <android/native_activity.h>
+#include <android/log.h>
+
+#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 {
+	
+    class PolycodeView : public PolycodeViewBase {
+        public:
+			PolycodeView(ANativeActivity* native, String title);
+			~PolycodeView();
+
+			String windowTitle;
+			
+			ANativeActivity* native_activity;
+			ANativeWindow* native_window;
+			AInputQueue* native_input;
+			
+// 			pthread_mutex_t* windowMutex;
+// 			pthread_cond_t* windowCond;
+    };
+}
+
+struct startHelper{
+	pthread_t thread;
+	pthread_mutex_t mutex;
+	pthread_cond_t cond;
+	ANativeActivity* activity;
+	int running;
+};
+
+void onStart(ANativeActivity* activity);
+void onResume(ANativeActivity* activity);
+void onPause(ANativeActivity* activity);
+void* onSaveInstanceState(ANativeActivity* activity, size_t *outSize);
+void onStop(ANativeActivity* activity);
+void onDestroy(ANativeActivity* activity);
+void onWindowFocusChanged(ANativeActivity* activity, int hasFocus);
+void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow *window);
+void onNativeWindowResized(ANativeActivity* activity, ANativeWindow *window);
+void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow *window);
+void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow *window);
+void onInputQueueCreated(ANativeActivity* activity, AInputQueue *queue);
+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);
+void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize);
+void* startApp(void* data);

+ 118 - 0
src/core/PolyAAssetFileProvider.cpp

@@ -0,0 +1,118 @@
+/*
+ Copyright (C) 2016 by Joachim Meyer
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+#include "polycode/core/PolyAAssetFileProvider.h"
+#include "polycode/core/PolyLogger.h"
+
+using namespace Polycode;
+
+AAssetFileProvider::AAssetFileProvider(AAssetManager* manager) {
+    type = "android";
+	this->manager = manager;
+	canListFiles = true;
+}
+
+void AAssetFileProvider::addSource(const String &source) {
+	AAssetDirClass dir;
+	dir.name = source;
+	dir.system = AAssetManager_openDir(manager, source.c_str());
+	sourceFolders.push_back(dir);
+	Logger::log("addSource");
+}
+
+void AAssetFileProvider::removeSource(const String &source) {
+    for(int i=0; i < sourceFolders.size(); i++) {
+        if(sourceFolders[i].name == source) {
+			AAssetDir_close(sourceFolders[i].system);
+            sourceFolders.erase(sourceFolders.begin()+i);
+            return;
+        }
+    }
+}
+
+Polycode::CoreFile *AAssetFileProvider::openFile(const String &fileName, const String &opts) {
+    Logger::log("openFile %s", fileName.c_str());
+    AAsset *file = NULL;
+    for(int i=0; i < sourceFolders.size(); i++) {
+        file = AAssetManager_open(manager, (sourceFolders[i].name+"/"+fileName).c_str(), AASSET_MODE_BUFFER);
+        if(file) {
+            break;
+        }
+    }
+    
+    if(!file) {
+        file = AAssetManager_open(manager, fileName.c_str(), AASSET_MODE_BUFFER);
+    }
+    
+    if(file) {
+        AAssetFile *retFile = NULL;
+        retFile = new AAssetFile();
+        retFile->file = file;
+        return retFile;
+    }
+    
+    return NULL;
+}
+
+bool AAssetFileProvider::parseFolder(const String& pathString, bool showHidden, std::vector< OSFileEntry >& targetVector){
+	Logger::log("Parse AAsset [%s]", pathString.c_str());
+	String path = pathString;
+	if(pathString.substr(pathString.length(),1)!="/")
+		path = pathString + "/";
+	
+	AAssetDir* dir = AAssetManager_openDir(manager, pathString.c_str());
+	if(!dir)
+		return false;
+	
+	while(true){
+		String name = AAssetDir_getNextFileName(dir);
+		if(name == "")
+			break;
+		Logger::log("Parse AAsset Found File: %s", (path+name).c_str());
+		OSFileEntry entry = OSFileEntry(path + name, OSFileEntry::TYPE_FILE);
+		targetVector.push_back(entry);
+	}
+	return true;
+}
+
+
+void AAssetFileProvider::closeFile(Polycode::CoreFile *file) {
+    AAssetFile *aassetFile = (AAssetFile*) file;
+    AAsset_close(aassetFile->file);
+    delete aassetFile;
+}
+
+long AAssetFile::read( void * ptr, size_t size, size_t count) {
+    return AAsset_read(file, ptr, count*size) / size;
+}
+
+long AAssetFile::write( const void * ptr, size_t size, size_t count) {
+    return 0;
+}
+
+int AAssetFile::seek(long int offset, int origin) {
+    return AAsset_seek(file, offset, origin);
+}
+
+long AAssetFile::tell() {
+    return AAsset_getLength(file);
+}

+ 367 - 0
src/core/PolyAndroidCore.cpp

@@ -0,0 +1,367 @@
+/*
+ Copyright (C) 2016 by Joachim Meyer
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+#include "polycode/core/PolyAndroidCore.h"
+// #include "polycode/core/PolyBasicFileProvider.h"
+#include "polycode/core/PolyOpenGLGraphicsInterface.h"
+#include "polycode/core/PolyAAssetFileProvider.h"
+#include "polycode/core/PolyLogger.h"
+#include "polycode/view/android/PolycodeView.h"
+
+// #include <EGL/egl.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+using namespace Polycode;
+
+extern AndroidCore *core;
+
+void AndroidCoreMutex::lock() {
+    pthread_mutex_lock(&pMutex);    
+}
+
+void AndroidCoreMutex::unlock() {
+    pthread_mutex_unlock(&pMutex);
+}
+
+
+AndroidCore::AndroidCore(PolycodeView *view, int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel, int frameRate, int monitorIndex, bool retinaSupport) 
+	: Core(xRes, yRes, fullScreen, vSync, aaLevel, anisotropyLevel, frameRate, monitorIndex) {
+	
+	fileProviders.push_back(new AAssetFileProvider(view->native_activity->assetManager));
+	renderer = new Renderer();
+	renderer->setBackingResolutionScale(1.0, 1.0);
+	graphicsInterface = new OpenGLGraphicsInterface();
+	renderer->setGraphicsInterface(this, graphicsInterface);
+	services->setRenderer(renderer);
+	
+	recreateContext = true;
+	setVideoMode(xRes, yRes, fullScreen, vSync, aaLevel, anisotropyLevel, retinaSupport);
+	//services->getSoundManager()->setAudioInterface(new XAudio2AudioInterface());
+	eventMutex = createMutex();
+	eglMutex = createMutex();
+	
+	paused = true;
+	
+	this->view = view;
+	core = this;
+	
+}
+
+AndroidCore::~AndroidCore() {
+
+}
+
+void AndroidCore::Render() {
+	renderer->beginFrame();
+	services->Render(Polycode::Rectangle(0, 0, xRes, yRes));
+	renderer->endFrame();
+}
+
+void AndroidCore::checkEvents() {
+
+	eventMutex->lock();
+	
+	AndroidEvent event;
+	for (int i = 0; i < systemInputEvents.size(); i++) {
+		event = systemInputEvents[i];
+		switch (event.eventGroup) {
+		case AndroidEvent::INPUT_EVENT:
+			switch (event.eventCode) {
+			case InputEvent::EVENT_MOUSEMOVE:
+				input->setDeltaPosition(lastMouseX - event.mouseX, lastMouseY - event.mouseY);
+				lastMouseX = event.mouseX;
+				lastMouseY = event.mouseY;
+				input->setMousePosition(event.mouseX, event.mouseY, getTicks());
+				break;
+			case InputEvent::EVENT_MOUSEDOWN:
+				input->mousePosition.x = event.mouseX;
+				input->mousePosition.y = event.mouseY;
+				input->setMouseButtonState(event.mouseButton, true, getTicks());
+				break;
+			case InputEvent::EVENT_MOUSEWHEEL_UP:
+				input->mouseWheelUp(getTicks());
+				break;
+			case InputEvent::EVENT_MOUSEWHEEL_DOWN:
+				input->mouseWheelDown(getTicks());
+				break;
+			case InputEvent::EVENT_MOUSEUP:
+				input->setMouseButtonState(event.mouseButton, false, getTicks());
+				break;
+			case InputEvent::EVENT_KEYDOWN:
+				if (!checkSpecialKeyEvents(event.keyCode))
+					input->setKeyState(event.keyCode, event.unicodeChar, true, getTicks());
+				break;
+			case InputEvent::EVENT_KEYUP:
+				input->setKeyState(event.keyCode, event.unicodeChar, false, getTicks());
+				break;
+			case InputEvent::EVENT_TOUCHES_BEGAN:
+				input->touchesBegan(event.touch, event.touches, getTicks());
+				break;
+			case InputEvent::EVENT_TOUCHES_ENDED:
+				input->touchesEnded(event.touch, event.touches, getTicks());
+				break;
+			case InputEvent::EVENT_TOUCHES_MOVED:
+				input->touchesMoved(event.touch, event.touches, getTicks());
+				break;
+			}
+			break;
+		case AndroidEvent::SYSTEM_FOCUS_EVENT:
+			switch (event.eventCode) {
+			case Core::EVENT_LOST_FOCUS:
+				loseFocus();
+				break;
+			case Core::EVENT_GAINED_FOCUS:
+				gainFocus();
+				break;
+			}
+			break;
+		}
+	}
+
+	systemInputEvents.clear();
+	eventMutex->unlock();
+
+}
+
+bool AndroidCore::systemUpdate() {
+	if (!running) {
+		Logger::log("not running...");
+		return false;
+	}
+	doSleep();
+	updateCore();
+
+	checkEvents();
+	return running;
+}
+
+void AndroidCore::setCursor(int cursorType) {
+
+}
+
+void launchThread(Threaded *target) {
+	target->runThread();
+	target->scheduledForRemoval = true;
+}
+
+void *ManagedThreadFunc(void *data) {
+	Threaded *target = static_cast<Threaded*>(data);
+	target->runThread();
+	target->scheduledForRemoval = true;
+	return NULL;
+}
+
+
+void AndroidCore::createThread(Threaded * target) {
+	Core::createThread(target);
+	pthread_t thread;
+	pthread_create( &thread, NULL, ManagedThreadFunc, (void*)target);
+}
+
+CoreMutex *AndroidCore::createMutex() {
+	AndroidCoreMutex *mutex = new AndroidCoreMutex();
+	pthread_mutex_init(&mutex->pMutex, NULL);
+	return mutex;
+}
+
+void AndroidCore::copyStringToClipboard(const String& str) {
+
+}
+
+String AndroidCore::getClipboardString() {
+	return "";
+}
+
+void AndroidCore::createFolder(const String& folderPath) {
+
+}
+
+void AndroidCore::copyDiskItem(const String& itemPath, const String& destItemPath) {
+
+}
+
+void AndroidCore::moveDiskItem(const String& itemPath, const String& destItemPath) {
+
+}
+
+void AndroidCore::removeDiskItem(const String& itemPath) {
+
+}
+
+String AndroidCore::openFolderPicker() {
+	return "";
+}
+
+std::vector<String> AndroidCore::openFilePicker(std::vector<CoreFileExtension> extensions, bool allowMultiple) {
+	std::vector<String> ret;
+	return ret;
+}
+
+String AndroidCore::saveFilePicker(std::vector<CoreFileExtension> extensions) {
+	return "";
+}
+
+void AndroidCore::handleVideoModeChange(VideoModeChangeInfo *modeInfo) {
+	Logger::log("handleVideoModeChange");
+	int32_t success = 0;
+	EGLBoolean result;
+	EGLint num_config;
+
+	this->xRes = modeInfo->xRes;
+	this->yRes = modeInfo->yRes;
+	this->fullScreen = modeInfo->fullScreen;
+	this->aaLevel = modeInfo->aaLevel;
+	this->vSync = modeInfo->vSync;
+	this->anisotropyLevel = modeInfo->anisotropyLevel;
+
+	if(!view->native_window){
+		Logger::log("handleVideoModeChange2");
+		return;
+	}
+	Logger::log("handleVideoModeChange3");
+	
+	if (recreateContext){
+		eglMutex->lock();
+		static const EGLint attribute_list[] =
+		{
+			EGL_RED_SIZE, 8,
+			EGL_GREEN_SIZE, 8,
+			EGL_BLUE_SIZE, 8,
+			EGL_ALPHA_SIZE, 8,
+			EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+			EGL_NONE
+		};
+
+		static const EGLint context_attributes[] =
+		{
+			EGL_CONTEXT_CLIENT_VERSION, 2,
+			EGL_NONE
+		};
+
+		EGLConfig config;
+		EGLint format;
+		Logger::log("handleVideoModeChange4");
+		display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+		result = eglInitialize(display, NULL, NULL);
+		result = eglChooseConfig(display, attribute_list, &config, 1, &num_config);
+		assert(EGL_FALSE != result);
+		Logger::log("Config chosen");
+		
+		if (eglQueryAPI() == EGL_NONE){
+			result = eglBindAPI(EGL_OPENGL_ES_API);
+			assert(EGL_FALSE != result);
+		}
+	
+		context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
+		assert(context!=EGL_NO_CONTEXT);
+
+		surface = eglCreateWindowSurface( display, config, view->native_window, NULL );
+		assert(surface != EGL_NO_SURFACE);
+
+		// connect the context to the surface
+		result = eglMakeCurrent(display, surface, surface, context);
+		assert(EGL_FALSE != result);
+		Logger::log("EGL Init finished");
+		
+		recreateContext = false;
+		eglMutex->unlock();
+	}
+}
+
+void AndroidCore::flushRenderContext() {
+	glFlush();
+	eglSwapBuffers(display, surface);
+}
+
+bool AndroidCore::isWindowInitialized(){
+	eglMutex->lock();
+	if (eglGetCurrentContext() == EGL_NO_CONTEXT){
+		eglMutex->unlock();
+		return false;
+	} else {
+		eglMutex->unlock();
+		return true;
+	}
+}
+
+void AndroidCore::openURL(String url) {
+
+}
+
+unsigned int AndroidCore::getTicks() {
+	struct timespec now;
+	clock_gettime(CLOCK_MONOTONIC, &now);
+	return now.tv_sec*1000000000LL + now.tv_nsec;
+}
+
+String AndroidCore::executeExternalCommand(String command, String args, String inDirectory) {
+	return "";
+}
+
+bool AndroidCore::systemParseFolder(const Polycode::String& pathString, bool showHidden, std::vector<OSFileEntry> &targetVector) {
+	
+    DIR           *d;
+    struct dirent *dir;
+    
+    d = opendir(pathString.c_str());
+    if(d) {
+        while ((dir = readdir(d)) != NULL) {
+            if(dir->d_name[0] != '.' || (dir->d_name[0] == '.'  && showHidden)) {
+                if(dir->d_type == DT_DIR) {
+                    targetVector.push_back(OSFileEntry(pathString, dir->d_name, OSFileEntry::TYPE_FOLDER));
+                } else {
+                    targetVector.push_back(OSFileEntry(pathString, dir->d_name, OSFileEntry::TYPE_FILE));
+                }
+            }
+        }
+        closedir(d);
+    }
+    return true;
+}
+
+void AndroidCore::handleSystemEvent(AndroidEvent systemEvent) {
+	eventMutex->lock();
+	systemInputEvents.push_back(systemEvent);
+	eventMutex->unlock();
+}
+
+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() {
+	return deviceWidth;
+}
+
+Number AndroidCore::getBackingYRes() {
+	return deviceHeight;
+}

+ 8 - 1
src/core/PolyLogger.cpp

@@ -24,7 +24,10 @@
 #ifdef _MSC_VER
 #ifdef _MSC_VER
 #include <windows.h>
 #include <windows.h>
 #endif
 #endif
-#include "polycode/core/PolyLogger.h"
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
 #include <stdio.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdarg.h>
 #include <string>
 #include <string>
@@ -68,7 +71,11 @@ void Logger::logw(const char *str) {
 void Logger::log(const char *format, ...) {
 void Logger::log(const char *format, ...) {
 	va_list args;
 	va_list args;
 	va_start(args, format);
 	va_start(args, format);
+#ifndef __ANDROID__
 	vfprintf(stderr, format, args);
 	vfprintf(stderr, format, args);
+#else
+	__android_log_vprint(ANDROID_LOG_INFO, "Polycode", format, args);
+#endif
 	va_end(args);
 	va_end(args);
 	
 	
 	if (Logger::getInstance()->getLogToFile()){
 	if (Logger::getInstance()->getLogToFile()){

+ 1 - 1
src/core/PolyMaterialManager.cpp

@@ -353,7 +353,7 @@ std::vector<Shader*> MaterialManager::loadShadersFromFile(ResourcePool *resource
 	} else {
 	} else {
 		TiXmlElement *mElem = doc.RootElement()->FirstChildElement("shaders");
 		TiXmlElement *mElem = doc.RootElement()->FirstChildElement("shaders");
 		if(mElem) {
 		if(mElem) {
-			TiXmlNode* pChild;					
+			TiXmlNode* pChild;
 			for (pChild = mElem->FirstChild(); pChild != 0; pChild = pChild->NextSibling()) {	
 			for (pChild = mElem->FirstChild(); pChild != 0; pChild = pChild->NextSibling()) {	
 				Shader *newShader = createShaderFromXMLNode(resourcePool, pChild);
 				Shader *newShader = createShaderFromXMLNode(resourcePool, pChild);
 				if(newShader != NULL) {
 				if(newShader != NULL) {

+ 7 - 6
src/core/PolyOpenGLGraphicsInterface.cpp

@@ -661,9 +661,10 @@ void OpenGLGraphicsInterface::destroyProgram(ShaderProgram *program) {
 
 
 void OpenGLGraphicsInterface::createProgram(ShaderProgram *program) {
 void OpenGLGraphicsInterface::createProgram(ShaderProgram *program) {
 
 
-	if(!program->platformData) {
-		program->platformData = (void*) new GLuint;
-	}
+    if(!program->platformData) {
+        program->platformData = (void*) new GLuint;
+		*((GLuint*)program->platformData) = 0;
+    }
 
 
 	GLuint programID = *((GLuint*)program->platformData);
 	GLuint programID = *((GLuint*)program->platformData);
 	if(programID != 0) {
 	if(programID != 0) {
@@ -749,7 +750,7 @@ void OpenGLGraphicsInterface::createShader(Shader *shader) {
 	glAttachShader(shaderID, *((GLuint*)shader->fragmentProgram->platformData));
 	glAttachShader(shaderID, *((GLuint*)shader->fragmentProgram->platformData));
 	glAttachShader(shaderID, *((GLuint*)shader->vertexProgram->platformData));
 	glAttachShader(shaderID, *((GLuint*)shader->vertexProgram->platformData));
 	glLinkProgram(shaderID);
 	glLinkProgram(shaderID);
-
+// 	Logger::log("createShader6");
 
 
 	GLint result;
 	GLint result;
 	glGetProgramiv( shaderID, GL_LINK_STATUS, &result);
 	glGetProgramiv( shaderID, GL_LINK_STATUS, &result);
@@ -757,7 +758,7 @@ void OpenGLGraphicsInterface::createShader(Shader *shader) {
 	if(result == GL_INVALID_VALUE || result == GL_INVALID_OPERATION) {
 	if(result == GL_INVALID_VALUE || result == GL_INVALID_OPERATION) {
 		Services()->getLogger()->logBroadcast("ERROR: Error linking shader. Invalid shader program.");
 		Services()->getLogger()->logBroadcast("ERROR: Error linking shader. Invalid shader program.");
 	}
 	}
-
+// 	Logger::log("createShader8");
 	int total = -1;
 	int total = -1;
 	glGetProgramiv( shaderID, GL_ACTIVE_UNIFORMS, &total );
 	glGetProgramiv( shaderID, GL_ACTIVE_UNIFORMS, &total );
 	for(int i=0; i < total; i++)  {
 	for(int i=0; i < total; i++)  {
@@ -788,7 +789,7 @@ void OpenGLGraphicsInterface::createShader(Shader *shader) {
 		
 		
 		glGetActiveAttrib(shaderID, i, sizeof(name)-1, &name_len, &num, &type, name);
 		glGetActiveAttrib(shaderID, i, sizeof(name)-1, &name_len, &num, &type, name);
 		name[name_len] = 0;
 		name[name_len] = 0;
-
+		
 		int attribLocation = glGetAttribLocation(shaderID, name);
 		int attribLocation = glGetAttribLocation(shaderID, name);
 		
 		
 		ProgramAttribute attribute;
 		ProgramAttribute attribute;

+ 22 - 6
src/core/PolyRenderer.cpp

@@ -26,6 +26,8 @@
 #include "polycode/core/PolyCore.h"
 #include "polycode/core/PolyCore.h"
 #include "polycode/core/PolyTexture.h"
 #include "polycode/core/PolyTexture.h"
 #include "polycode/core/PolyVector4.h"
 #include "polycode/core/PolyVector4.h"
+#include "polycode/core/PolyLogger.h"
+#include <unistd.h>
 
 
 using namespace Polycode;
 using namespace Polycode;
 
 
@@ -81,22 +83,22 @@ void RenderThread::initGlobals() {
 void RenderThread::updateRenderThread() {
 void RenderThread::updateRenderThread() {
 	jobQueueMutex->lock();
 	jobQueueMutex->lock();
 		
 		
-	while(jobQueue.size() > 0) {
+	while (jobQueue.size() > 0) {
 		RendererThreadJob nextJob = jobQueue.front();
 		RendererThreadJob nextJob = jobQueue.front();
 		jobQueue.pop();
 		jobQueue.pop();
 		processJob(nextJob);
 		processJob(nextJob);
 	}
 	}
-		
+
 	RenderFrame *nextFrame = NULL;
 	RenderFrame *nextFrame = NULL;
-	if(frameQueue.size() > 0) {
+	if (frameQueue.size() > 0) {
 		nextFrame = frameQueue.front();
 		nextFrame = frameQueue.front();
 		frameQueue.pop();
 		frameQueue.pop();
 	}
 	}
 
 
 	jobQueueMutex->unlock();
 	jobQueueMutex->unlock();
 
 
-	if(nextFrame) {
-		while(nextFrame->jobQueue.size() > 0) {
+	if (nextFrame) {
+		while (nextFrame->jobQueue.size() > 0) {
 			RendererThreadJob frameJob = nextFrame->jobQueue.front();
 			RendererThreadJob frameJob = nextFrame->jobQueue.front();
 			nextFrame->jobQueue.pop();
 			nextFrame->jobQueue.pop();
 			processJob(frameJob);
 			processJob(frameJob);
@@ -111,7 +113,7 @@ void RenderThread::updateRenderThread() {
 }
 }
 
 
 void RenderThread::runThread() {
 void RenderThread::runThread() {
-	
+
 	initGlobals();
 	initGlobals();
 	
 	
 	while(threadRunning) {
 	while(threadRunning) {
@@ -330,6 +332,20 @@ void RenderThread::clearFrameQueue() {
 
 
 void RenderThread::processJob(const RendererThreadJob &job) {
 void RenderThread::processJob(const RendererThreadJob &job) {
 	lockRenderMutex();
 	lockRenderMutex();
+	if (!core->isWindowInitialized() && job.jobType != JOB_REQUEST_CONTEXT_CHANGE) {
+		jobQueue.push(job);
+		for (int i = 0; i < jobQueue.size() - 1; i++) {
+			RendererThreadJob fJob = jobQueue.front();
+			if (fJob.jobType != JOB_REQUEST_CONTEXT_CHANGE) {
+				jobQueue.push(fJob);
+			} else {
+				processJob(fJob);
+				i--;
+			}
+			jobQueue.pop();
+		}
+		return;
+	}
 	switch(job.jobType) {
 	switch(job.jobType) {
 		case JOB_REQUEST_CONTEXT_CHANGE:
 		case JOB_REQUEST_CONTEXT_CHANGE:
 		{
 		{

+ 236 - 0
src/view/android/PolycodeView.cpp

@@ -0,0 +1,236 @@
+/*
+ Copyright (C) 2016 by Joachim Meyer
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+#include "polycode/view/android/PolycodeView.h"
+#include "polycode/core/PolyLogger.h"
+#include <android/looper.h>
+
+using namespace Polycode;
+
+AndroidCore* core = NULL;
+extern void android_main(struct startHelper* helper);
+
+PolycodeView::PolycodeView(ANativeActivity* native, String title){
+	windowTitle = title;
+	
+	native_activity = native;
+	native_window = NULL;
+	native_input = NULL;
+	
+// 	pthread_mutex_init(windowMutex, NULL);
+//     pthread_cond_init(windowCond, NULL);
+	
+	native_activity->instance = this;
+	native_activity->callbacks->onStart 				= onStart;
+	native_activity->callbacks->onStop 					= onStop;
+	native_activity->callbacks->onDestroy				= onDestroy;
+	native_activity->callbacks->onNativeWindowCreated 	= onNativeWindowCreated;
+	native_activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
+	native_activity->callbacks->onResume 				= onResume;
+	native_activity->callbacks->onPause 				= onPause;
+	native_activity->callbacks->onWindowFocusChanged 	= onWindowFocusChanged;
+	native_activity->callbacks->onInputQueueCreated		= onInputQueueCreated;
+	native_activity->callbacks->onInputQueueDestroyed	= onInputQueueDestroyed;
+}
+
+PolycodeView::~PolycodeView(){
+	
+}
+
+void onStart(ANativeActivity* activity){
+	Logger::log("onStart");
+	if(core)
+	core->paused = false;
+}
+
+void onResume(ANativeActivity* activity){
+	Logger::log("onResume");
+	if(core)
+	core->paused = false;
+}
+
+void onPause(ANativeActivity* activity){
+	Logger::log("onPause");
+	if(core)
+	core->paused = true;
+}
+
+void* onSaveInstanceState(ANativeActivity* activity, size_t *outSize){
+	
+}
+
+void onStop(ANativeActivity* activity){
+	Logger::log("onStop");
+	if(core)
+	core->paused = true;
+}
+
+void onDestroy(ANativeActivity* activity){
+	Logger::log("onDestroy");
+	if(core)
+		core->Shutdown();
+}
+
+void onWindowFocusChanged(ANativeActivity* activity, int hasFocus){
+	Logger::log("onWindowFocusChanged");
+	if(hasFocus){
+		AndroidEvent event = AndroidEvent();
+		event.eventGroup = AndroidEvent::SYSTEM_FOCUS_EVENT;
+		event.eventCode = Core::EVENT_GAINED_FOCUS;
+		if(core)
+			core->handleSystemEvent(event);
+	}else{
+		AndroidEvent event = AndroidEvent();
+		event.eventGroup = AndroidEvent::SYSTEM_FOCUS_EVENT;
+		event.eventCode = Core::EVENT_LOST_FOCUS;
+		if(core)
+			core->handleSystemEvent(event);		
+	}
+}
+
+void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow *window){
+	Logger::log("onNativeWindowCreated");
+	((PolycodeView*)activity->instance)->native_window = window;
+	int width = ANativeWindow_getWidth(window);
+	int height = ANativeWindow_getHeight(window);
+	if (width < 0)
+		width = 100;
+	if (height)
+		height = 100;
+	if(core){
+		core->recreateContext = true;
+		core->setVideoMode(width, height, true, false, core->getAALevel(), 0, (core->getBackingXRes() > core->getXRes()));
+	}
+	Logger::log("core exists");
+}
+
+void onNativeWindowResized(ANativeActivity* activity, ANativeWindow *window){
+	
+}
+
+void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow *window){
+	
+}
+
+void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow *window){
+	Logger::log("onNativeWindowDestroyed");
+	((PolycodeView*)activity->instance)->native_window = NULL;
+	if (core)
+		core->recreateContext = true;
+}
+
+void onInputQueueCreated(ANativeActivity* activity, AInputQueue *queue){
+	Logger::log("onInputQueueCreated");
+	((PolycodeView*)activity->instance)->native_input = queue;
+	ALooper *loop = ALooper_prepare(0);
+	AInputQueue_attachLooper(((PolycodeView*)activity->instance)->native_input, loop, ALOOPER_EVENT_INPUT, inputLoop, ((PolycodeView*)activity->instance)->native_input);
+}
+
+void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue *queue){
+	Logger::log("onInputQueueDestroyed");
+	((PolycodeView*)activity->instance)->native_input = NULL;
+	AInputQueue_detachLooper(((PolycodeView*)activity->instance)->native_input);
+}
+
+void onContentRectChanged(ANativeActivity* activity, const ARect *rect){
+	
+}
+
+void onConfiguartionChanged(ANativeActivity* activity){
+	
+}
+
+void onLowMemory(ANativeActivity* activity){
+	
+}
+
+int inputLoop(int fd, int events, void* data){
+	Logger::log("inputLoop");
+	AInputQueue* native_input = (AInputQueue*)data;
+	AndroidEvent event;
+	AInputEvent* aev;
+	int type;
+	int action;
+	
+	while(AInputQueue_hasEvents(native_input)>0){
+		if(AInputQueue_getEvent(native_input, &aev)>=0){
+			event = AndroidEvent();
+			event.eventTime = AKeyEvent_getEventTime(aev);
+			event.eventGroup = AndroidEvent::INPUT_EVENT;
+			type = AInputEvent_getType(aev);
+			if(type == AINPUT_EVENT_TYPE_KEY){
+				action = AKeyEvent_getAction(aev);
+				if(action == AKEY_EVENT_ACTION_DOWN){
+					event.eventCode = InputEvent::EVENT_KEYDOWN;
+				} else if (action == AKEY_EVENT_ACTION_UP){
+					event.eventCode = InputEvent::EVENT_KEYUP;
+				}
+				
+			} else if(type == AINPUT_EVENT_TYPE_MOTION){
+				
+			}
+		}
+	}
+}
+
+void ANativeActivity_onCreate(ANativeActivity* activity, void *savedState, size_t savedStateSize) {
+	Logger::log("onCreate");
+	
+	struct startHelper* helper = new struct startHelper;
+	helper->activity = activity;
+	helper->running = 0;
+	pthread_mutex_init(&helper->mutex, NULL);
+    pthread_cond_init(&helper->cond, NULL);
+	
+	pthread_attr_t attr; 
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+    pthread_create(&helper->thread, &attr, startApp, helper);
+
+    // Wait for thread to start.
+    pthread_mutex_lock(&helper->mutex);
+    while (!helper->running) {
+        pthread_cond_wait(&helper->cond, &helper->mutex);
+    }
+    pthread_mutex_unlock(&helper->mutex);
+}
+
+void* startApp(void* data){
+	Logger::log("startApp");
+	startHelper* helper = (startHelper*)data;
+	
+// 	pthread_mutex_lock(&helper->mutex);
+//     helper->running = 1;
+//     pthread_cond_broadcast(&helper->cond);
+//     pthread_mutex_unlock(&helper->mutex);
+	
+	android_main(helper);
+	Logger::log("startApp4");
+    pthread_mutex_lock(&helper->mutex);
+    if (((PolycodeView*)helper->activity->instance)->native_input != NULL) {
+        AInputQueue_detachLooper(((PolycodeView*)helper->activity->instance)->native_input);
+    }
+    
+    pthread_cond_broadcast(&helper->cond);
+    pthread_mutex_unlock(&helper->mutex);
+	delete helper;
+}

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません