diff options
| author | Juan Linietsky | 2014-02-09 22:10:30 -0300 |
|---|---|---|
| committer | Juan Linietsky | 2014-02-09 22:10:30 -0300 |
| commit | 0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch) | |
| tree | 276c4d099e178eb67fbd14f61d77b05e3808e9e3 /platform/android/java | |
| parent | 0e49da1687bc8192ed210947da52c9e5c5f301bb (diff) | |
| download | godot-0b806ee.tar.gz godot-0b806ee.tar.zst godot-0b806ee.zip | |
GODOT IS OPEN SOURCE
Diffstat (limited to '')
54 files changed, 2903 insertions, 0 deletions
diff --git a/platform/android/java/ant.properties b/platform/android/java/ant.properties new file mode 100644 index 000000000..950b8b019 --- /dev/null +++ b/platform/android/java/ant.properties @@ -0,0 +1,22 @@ +# This file is used to override default values used by the Ant build system. +# +# This file must be checked into Version Control Systems, as it is +# integral to the build system of your project. + +# This file is only used by the Ant script. + +# You can use this to override default values such as +# 'source.dir' for the location of your java source folder and +# 'out.dir' for the location of your output folder. + +# You can also use it define how the release builds are signed by declaring +# the following properties: +# 'key.store' for the location of your keystore and +# 'key.alias' for the name of the key to use. +# The password will be asked during the build when you use the 'release' target. + +key.store=my-release-key.keystore +key.alias=mykey + +key.store.password=123456 +key.alias.password=123456 diff --git a/platform/android/java/build.properties b/platform/android/java/build.properties new file mode 100644 index 000000000..ee52d86d9 --- /dev/null +++ b/platform/android/java/build.properties @@ -0,0 +1,17 @@ +# This file is used to override default values used by the Ant build system. +# +# This file must be checked in Version Control Systems, as it is +# integral to the build system of your project. + +# This file is only used by the Ant script. + +# You can use this to override default values such as +# 'source.dir' for the location of your java source folder and +# 'out.dir' for the location of your output folder. + +# You can also use it define how the release builds are signed by declaring +# the following properties: +# 'key.store' for the location of your keystore and +# 'key.alias' for the name of the key to use. +# The password will be asked during the build when you use the 'release' target. + diff --git a/platform/android/java/build.xml b/platform/android/java/build.xml new file mode 100644 index 000000000..424e2827d --- /dev/null +++ b/platform/android/java/build.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project name="Godot" default="help"> + + <!-- The local.properties file is created and updated by the 'android' tool. + It contains the path to the SDK. It should *NOT* be checked into + Version Control Systems. --> + <property file="local.properties" /> + + <!-- The ant.properties file can be created by you. It is only edited by the + 'android' tool to add properties to it. + This is the place to change some Ant specific build properties. + Here are some properties you may want to change/update: + + source.dir + The name of the source directory. Default is 'src'. + out.dir + The name of the output directory. Default is 'bin'. + + For other overridable properties, look at the beginning of the rules + files in the SDK, at tools/ant/build.xml + + Properties related to the SDK location or the project target should + be updated using the 'android' tool with the 'update' action. + + This file is an integral part of the build system for your + application and should be checked into Version Control Systems. + + --> + <property file="ant.properties" /> + + <!-- if sdk.dir was not set from one of the property file, then + get it from the ANDROID_HOME env var. + This must be done before we load project.properties since + the proguard config can use sdk.dir --> + <property environment="env" /> + <condition property="sdk.dir" value="${env.ANDROID_HOME}"> + <isset property="env.ANDROID_HOME" /> + </condition> + + <!-- The project.properties file is created and updated by the 'android' + tool, as well as ADT. + + This contains project specific properties such as project target, and library + dependencies. Lower level build properties are stored in ant.properties + (or in .classpath for Eclipse projects). + + This file is an integral part of the build system for your + application and should be checked into Version Control Systems. --> + <loadproperties srcFile="project.properties" /> + + <!-- quick check on sdk.dir --> + <fail + message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable." + unless="sdk.dir" + /> + + <!-- + Import per project custom build rules if present at the root of the project. + This is the place to put custom intermediary targets such as: + -pre-build + -pre-compile + -post-compile (This is typically used for code obfuscation. + Compiled code location: ${out.classes.absolute.dir} + If this is not done in place, override ${out.dex.input.absolute.dir}) + -post-package + -post-build + -pre-clean + --> + <import file="custom_rules.xml" optional="true" /> + + <!-- Import the actual build file. + + To customize existing targets, there are two options: + - Customize only one target: + - copy/paste the target into this file, *before* the + <import> task. + - customize it to your needs. + - Customize the whole content of build.xml + - copy/paste the content of the rules files (minus the top node) + into this file, replacing the <import> task. + - customize to your needs. + + *********************** + ****** IMPORTANT ****** + *********************** + In all cases you must update the value of version-tag below to read 'custom' instead of an integer, + in order to avoid having your file be overridden by tools such as "android update project" + --> + <!-- version-tag: 1 --> + <import file="${sdk.dir}/tools/ant/build.xml" /> + +</project> diff --git a/platform/android/java/default.properties b/platform/android/java/default.properties new file mode 100644 index 000000000..e2e8061f2 --- /dev/null +++ b/platform/android/java/default.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-8 diff --git a/platform/android/java/my-release-key.keystore b/platform/android/java/my-release-key.keystore Binary files differnew file mode 100644 index 000000000..410cccd86 --- /dev/null +++ b/platform/android/java/my-release-key.keystore diff --git a/platform/android/java/proguard-project.txt b/platform/android/java/proguard-project.txt new file mode 100644 index 000000000..f2fe1559a --- /dev/null +++ b/platform/android/java/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# 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 *; +#} diff --git a/platform/android/java/proguard.cfg b/platform/android/java/proguard.cfg new file mode 100644 index 000000000..12dd0392c --- /dev/null +++ b/platform/android/java/proguard.cfg @@ -0,0 +1,36 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native <methods>; +} + +-keepclasseswithmembernames class * { + public <init>(android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembernames class * { + public <init>(android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/platform/android/java/res/drawable/icon.png b/platform/android/java/res/drawable/icon.png Binary files differnew file mode 100644 index 000000000..050a1cf93 --- /dev/null +++ b/platform/android/java/res/drawable/icon.png diff --git a/platform/android/java/res/values-ar/strings.xml b/platform/android/java/res/values-ar/strings.xml new file mode 100644 index 000000000..9f3dc6d6a --- /dev/null +++ b/platform/android/java/res/values-ar/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-ar</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-bg/strings.xml b/platform/android/java/res/values-bg/strings.xml new file mode 100644 index 000000000..bd8109277 --- /dev/null +++ b/platform/android/java/res/values-bg/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-bg</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-ca/strings.xml b/platform/android/java/res/values-ca/strings.xml new file mode 100644 index 000000000..494cb8846 --- /dev/null +++ b/platform/android/java/res/values-ca/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-ca</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-cs/strings.xml b/platform/android/java/res/values-cs/strings.xml new file mode 100644 index 000000000..30ce00f89 --- /dev/null +++ b/platform/android/java/res/values-cs/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-cs</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-da/strings.xml b/platform/android/java/res/values-da/strings.xml new file mode 100644 index 000000000..4c2a1cf0f --- /dev/null +++ b/platform/android/java/res/values-da/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-da</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-de/strings.xml b/platform/android/java/res/values-de/strings.xml new file mode 100644 index 000000000..52946d4cc --- /dev/null +++ b/platform/android/java/res/values-de/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-de</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-el/strings.xml b/platform/android/java/res/values-el/strings.xml new file mode 100644 index 000000000..181dc5176 --- /dev/null +++ b/platform/android/java/res/values-el/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-el</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-en/strings.xml b/platform/android/java/res/values-en/strings.xml new file mode 100644 index 000000000..976a56501 --- /dev/null +++ b/platform/android/java/res/values-en/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-en</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-es-rES/strings.xml b/platform/android/java/res/values-es-rES/strings.xml new file mode 100644 index 000000000..73f63a08f --- /dev/null +++ b/platform/android/java/res/values-es-rES/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-es_ES</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-es/strings.xml b/platform/android/java/res/values-es/strings.xml new file mode 100644 index 000000000..07b718a64 --- /dev/null +++ b/platform/android/java/res/values-es/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-es</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-fi/strings.xml b/platform/android/java/res/values-fi/strings.xml new file mode 100644 index 000000000..323d82aff --- /dev/null +++ b/platform/android/java/res/values-fi/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-fi</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-fr/strings.xml b/platform/android/java/res/values-fr/strings.xml new file mode 100644 index 000000000..32bead266 --- /dev/null +++ b/platform/android/java/res/values-fr/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-fr</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-he/strings.xml b/platform/android/java/res/values-he/strings.xml new file mode 100644 index 000000000..f52ede208 --- /dev/null +++ b/platform/android/java/res/values-he/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-he</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-hi/strings.xml b/platform/android/java/res/values-hi/strings.xml new file mode 100644 index 000000000..8aab2a8c6 --- /dev/null +++ b/platform/android/java/res/values-hi/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-hi</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-hr/strings.xml b/platform/android/java/res/values-hr/strings.xml new file mode 100644 index 000000000..caf55e224 --- /dev/null +++ b/platform/android/java/res/values-hr/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-hr</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-hu/strings.xml b/platform/android/java/res/values-hu/strings.xml new file mode 100644 index 000000000..e7f9e5122 --- /dev/null +++ b/platform/android/java/res/values-hu/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-hu</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-id/strings.xml b/platform/android/java/res/values-id/strings.xml new file mode 100644 index 000000000..9e9a8b0c0 --- /dev/null +++ b/platform/android/java/res/values-id/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-id</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-it/strings.xml b/platform/android/java/res/values-it/strings.xml new file mode 100644 index 000000000..1f5e5a049 --- /dev/null +++ b/platform/android/java/res/values-it/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-it</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-ja/strings.xml b/platform/android/java/res/values-ja/strings.xml new file mode 100644 index 000000000..7f85f57df --- /dev/null +++ b/platform/android/java/res/values-ja/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-ja</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-ko/strings.xml b/platform/android/java/res/values-ko/strings.xml new file mode 100644 index 000000000..6d27498af --- /dev/null +++ b/platform/android/java/res/values-ko/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-ko</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-lt/strings.xml b/platform/android/java/res/values-lt/strings.xml new file mode 100644 index 000000000..6e3677fde --- /dev/null +++ b/platform/android/java/res/values-lt/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-lt</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-lv/strings.xml b/platform/android/java/res/values-lv/strings.xml new file mode 100644 index 000000000..701fc271a --- /dev/null +++ b/platform/android/java/res/values-lv/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-lv</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-nb/strings.xml b/platform/android/java/res/values-nb/strings.xml new file mode 100644 index 000000000..73147ca1a --- /dev/null +++ b/platform/android/java/res/values-nb/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-nb</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-nl/strings.xml b/platform/android/java/res/values-nl/strings.xml new file mode 100644 index 000000000..e501928a3 --- /dev/null +++ b/platform/android/java/res/values-nl/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-nl</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-pl/strings.xml b/platform/android/java/res/values-pl/strings.xml new file mode 100644 index 000000000..ea5da73b6 --- /dev/null +++ b/platform/android/java/res/values-pl/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-pl</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-pt/strings.xml b/platform/android/java/res/values-pt/strings.xml new file mode 100644 index 000000000..bdda7cd2c --- /dev/null +++ b/platform/android/java/res/values-pt/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-pt</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-ro/strings.xml b/platform/android/java/res/values-ro/strings.xml new file mode 100644 index 000000000..3686da4c1 --- /dev/null +++ b/platform/android/java/res/values-ro/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-ro</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-ru/strings.xml b/platform/android/java/res/values-ru/strings.xml new file mode 100644 index 000000000..954067658 --- /dev/null +++ b/platform/android/java/res/values-ru/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-ru</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-sk/strings.xml b/platform/android/java/res/values-sk/strings.xml new file mode 100644 index 000000000..37d128312 --- /dev/null +++ b/platform/android/java/res/values-sk/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-sk</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-sl/strings.xml b/platform/android/java/res/values-sl/strings.xml new file mode 100644 index 000000000..0bb249c37 --- /dev/null +++ b/platform/android/java/res/values-sl/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-sl</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-sr/strings.xml b/platform/android/java/res/values-sr/strings.xml new file mode 100644 index 000000000..0e83cab1a --- /dev/null +++ b/platform/android/java/res/values-sr/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-sr</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-sv/strings.xml b/platform/android/java/res/values-sv/strings.xml new file mode 100644 index 000000000..e3a04ac2e --- /dev/null +++ b/platform/android/java/res/values-sv/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-sv</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-th/strings.xml b/platform/android/java/res/values-th/strings.xml new file mode 100644 index 000000000..0aa893b8b --- /dev/null +++ b/platform/android/java/res/values-th/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-th</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-tl/strings.xml b/platform/android/java/res/values-tl/strings.xml new file mode 100644 index 000000000..e7e2af490 --- /dev/null +++ b/platform/android/java/res/values-tl/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-tl</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-tr/strings.xml b/platform/android/java/res/values-tr/strings.xml new file mode 100644 index 000000000..97af1243a --- /dev/null +++ b/platform/android/java/res/values-tr/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-tr</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-uk/strings.xml b/platform/android/java/res/values-uk/strings.xml new file mode 100644 index 000000000..3dea6908a --- /dev/null +++ b/platform/android/java/res/values-uk/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-uk</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-vi/strings.xml b/platform/android/java/res/values-vi/strings.xml new file mode 100644 index 000000000..a6552130b --- /dev/null +++ b/platform/android/java/res/values-vi/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-vi</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values-zh/strings.xml b/platform/android/java/res/values-zh/strings.xml new file mode 100644 index 000000000..397e66285 --- /dev/null +++ b/platform/android/java/res/values-zh/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name-zh</string> +</resources>
\ No newline at end of file diff --git a/platform/android/java/res/values/strings.xml b/platform/android/java/res/values/strings.xml new file mode 100644 index 000000000..3a38d4059 --- /dev/null +++ b/platform/android/java/res/values/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="godot_project_name_string">godot-project-name</string> + <string name="testuf8">元気です</string> + <string name="testuf2">元気です元気です元気です</string> + +</resources> diff --git a/platform/android/java/src/com/android/godot/Dictionary.java b/platform/android/java/src/com/android/godot/Dictionary.java new file mode 100644 index 000000000..4ed12f581 --- /dev/null +++ b/platform/android/java/src/com/android/godot/Dictionary.java @@ -0,0 +1,80 @@ +/*************************************************************************/ +/* Dictionary.java */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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. */ +/*************************************************************************/ +package com.android.godot; + +import java.util.HashMap; +import java.util.Set; + + +public class Dictionary extends HashMap<String, Object> { + + protected String[] keys_cache; + + public String[] get_keys() { + + String[] ret = new String[size()]; + int i=0; + Set<String> keys = keySet(); + for (String key : keys) { + + ret[i] = key; + i++; + }; + + return ret; + }; + + public Object[] get_values() { + + Object[] ret = new Object[size()]; + int i=0; + Set<String> keys = keySet(); + for (String key : keys) { + + ret[i] = get(key); + i++; + }; + + return ret; + }; + + public void set_keys(String[] keys) { + keys_cache = keys; + }; + + public void set_values(Object[] vals) { + + int i=0; + for (String key : keys_cache) { + put(key, vals[i]); + i++; + }; + keys_cache = null; + }; +}; diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java new file mode 100644 index 000000000..cf1545df8 --- /dev/null +++ b/platform/android/java/src/com/android/godot/Godot.java @@ -0,0 +1,300 @@ +/*************************************************************************/ +/* Godot.java */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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. */ +/*************************************************************************/ +package com.android.godot; + +import android.app.Activity; +import android.os.Bundle; +import android.view.MotionEvent; +import android.widget.RelativeLayout; +import android.widget.LinearLayout; +import android.view.ViewGroup.LayoutParams; + + +import android.app.*; +import android.content.*; +import android.view.*; +import android.view.inputmethod.InputMethodManager; +import android.os.*; +import android.util.Log; +import android.graphics.*; +import android.text.method.*; +import android.text.*; +import android.media.*; +import android.hardware.*; +import android.content.*; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.ArrayList; +import android.provider.Settings.Secure; + + +public class Godot extends Activity implements SensorEventListener +{ + + static public class SingletonBase { + + protected void registerClass(String p_name, String[] p_methods) { + + GodotLib.singleton(p_name,this); + + Class clazz = getClass(); + Method[] methods = clazz.getDeclaredMethods(); + for (Method method : methods) { + boolean found=false; + System.out.printf("METHOD: %s\n",method.getName()); + + for (String s : p_methods) { + System.out.printf("METHOD CMP WITH: %s\n",s); + if (s.equals(method.getName())) { + found=true; + System.out.printf("METHOD CMP VALID"); + break; + } + } + if (!found) + continue; + + System.out.printf("METHOD FOUND: %s\n",method.getName()); + + List<String> ptr = new ArrayList<String>(); + + Class[] paramTypes = method.getParameterTypes(); + for (Class c : paramTypes) { + ptr.add(c.getName()); + } + + String[] pt = new String[ptr.size()]; + ptr.toArray(pt); + + GodotLib.method(p_name,method.getName(),method.getReturnType().getName(),pt); + + + } + } + + public void registerMethods() {} + } + +/* + protected List<SingletonBase> singletons = new ArrayList<SingletonBase>(); + protected void instanceSingleton(SingletonBase s) { + + s.registerMethods(); + singletons.add(s); + } + +*/ + + public GodotView mView; + + private SensorManager mSensorManager; + private Sensor mAccelerometer; + + public RelativeLayout layout; + + + static public GodotIO io; + + public static void setWindowTitle(String title) { + //setTitle(title); + } + + public interface ResultCallback { + public void callback(int requestCode, int resultCode, Intent data); + }; + public ResultCallback result_callback; + + @Override protected void onActivityResult (int requestCode, int resultCode, Intent data) { + if (result_callback != null) { + result_callback.callback(requestCode, resultCode, data); + result_callback = null; + }; + }; + + public void onVideoInit(boolean use_gl2) { + +// mView = new GodotView(getApplication(),io,use_gl2); +// setContentView(mView); + + layout = new RelativeLayout(this); + layout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT)); + setContentView(layout); + mView = new GodotView(getApplication(),io,use_gl2, this); + layout.addView(mView,new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT)); + mView.setKeepScreenOn(true); + + } + + @Override protected void onCreate(Bundle icicle) { + + + super.onCreate(icicle); + + + + Window window = getWindow(); + window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON + | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + io = new GodotIO(this); + io.unique_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID); + GodotLib.io=io; + GodotLib.initialize(this,io.needsReloadHooks()); + mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); + mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); + + result_callback = null; + + // instanceSingleton( new GodotFacebook(this) ); + + + } + + @Override protected void onPause() { + super.onPause(); + mView.onPause(); + mSensorManager.unregisterListener(this); + GodotLib.focusout(); + + } + + @Override protected void onResume() { + super.onResume(); + mView.onResume(); + mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); + GodotLib.focusin(); + } + + @Override public void onSensorChanged(SensorEvent event) { + float x = event.values[0]; + float y = event.values[1]; + float z = event.values[2]; + GodotLib.accelerometer(x,y,z); + } + + @Override public final void onAccuracyChanged(Sensor sensor, int accuracy) { + // Do something here if sensor accuracy changes. + } + +/* + @Override public boolean dispatchKeyEvent(KeyEvent event) { + + if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) { + + System.out.printf("** BACK REQUEST!\n"); + + GodotLib.quit(); + return true; + } + System.out.printf("** OTHER KEY!\n"); + + return false; + } +*/ + + @Override public void onBackPressed() { + + GodotLib.quit(); + } + + public void forceQuit() { + + System.exit(0); + } + + + //@Override public boolean dispatchTouchEvent (MotionEvent event) { + public boolean gotTouchEvent(MotionEvent event) { + + super.onTouchEvent(event); + int evcount=event.getPointerCount(); + if (evcount==0) + return true; + + int[] arr = new int[event.getPointerCount()*3]; + + for(int i=0;i<event.getPointerCount();i++) { + + arr[i*3+0]=(int)event.getPointerId(i); + arr[i*3+1]=(int)event.getX(i); + arr[i*3+2]=(int)event.getY(i); + } + + //System.out.printf("gaction: %d\n",event.getAction()); + switch(event.getAction()&MotionEvent.ACTION_MASK) { + + case MotionEvent.ACTION_DOWN: { + GodotLib.touch(0,0,evcount,arr); + //System.out.printf("action down at: %f,%f\n", event.getX(),event.getY()); + } break; + case MotionEvent.ACTION_MOVE: { + GodotLib.touch(1,0,evcount,arr); + //for(int i=0;i<event.getPointerCount();i++) { + // System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i)); + //} + } break; + case MotionEvent.ACTION_POINTER_UP: { + int pointer_idx = event.getActionIndex(); + GodotLib.touch(4,pointer_idx,evcount,arr); + //System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx)); + } break; + case MotionEvent.ACTION_POINTER_DOWN: { + int pointer_idx = event.getActionIndex(); + GodotLib.touch(3,pointer_idx,evcount,arr); + //System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx)); + } break; + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: { + GodotLib.touch(2,0,evcount,arr); + //for(int i=0;i<event.getPointerCount();i++) { + // System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i)); + //} + } break; + + } + return true; + } + + @Override public boolean onKeyUp(int keyCode, KeyEvent event) { + GodotLib.key(event.getUnicodeChar(0), false); + return super.onKeyUp(keyCode, event); + }; + + @Override public boolean onKeyDown(int keyCode, KeyEvent event) { + GodotLib.key(event.getUnicodeChar(0), true); + return super.onKeyDown(keyCode, event); + }; + + + // Audio + + +} diff --git a/platform/android/java/src/com/android/godot/GodotIO.java b/platform/android/java/src/com/android/godot/GodotIO.java new file mode 100644 index 000000000..1f3967cb8 --- /dev/null +++ b/platform/android/java/src/com/android/godot/GodotIO.java @@ -0,0 +1,514 @@ +/*************************************************************************/ +/* GodotIO.java */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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. */ +/*************************************************************************/ +package com.android.godot; +import java.util.HashMap; +import java.util.Locale; +import android.net.Uri; +import android.content.Intent; +import android.content.res.AssetManager; +import java.io.InputStream; +import java.io.IOException; +import android.app.*; +import android.content.*; +import android.view.*; +import android.view.inputmethod.InputMethodManager; +import android.os.*; +import android.util.Log; +import android.graphics.*; +import android.text.method.*; +import android.text.*; +import android.media.*; +import android.hardware.*; +import android.content.*; +import android.content.pm.ActivityInfo; +//android.os.Build + +// Wrapper for native library + +public class GodotIO { + + + AssetManager am; + Activity activity; + + final int SCREEN_LANDSCAPE=0; + final int SCREEN_PORTRAIT=1; + final int SCREEN_REVERSE_LANDSCAPE=2; + final int SCREEN_REVERSE_PORTRAIT=3; + final int SCREEN_SENSOR_LANDSCAPE=4; + final int SCREEN_SENSOR_PORTRAIT=5; + final int SCREEN_SENSOR=6; + + ///////////////////////// + /// FILES + ///////////////////////// + + public int last_file_id=1; + + class AssetData { + + + public boolean eof=false; + public String path; + public InputStream is; + public int len; + public int pos; + } + + + HashMap<Integer,AssetData> streams; + + + public int file_open(String path,boolean write) { + + //System.out.printf("file_open: Attempt to Open %s\n",path); + + if (write) + return -1; + + + AssetData ad = new AssetData(); + + try { + ad.is = am.open(path); + + } catch (Exception e) { + + //System.out.printf("Exception on file_open: %s\n",e); + return -1; + } + + try { + ad.len=ad.is.available(); + } catch (Exception e) { + + System.out.printf("Exception availabling on file_open: %s\n",e); + return -1; + } + + ad.path=path; + ad.pos=0; + ++last_file_id; + streams.put(last_file_id,ad); + + return last_file_id; + } + public int file_get_size(int id) { + + if (!streams.containsKey(id)) { + System.out.printf("file_get_size: Invalid file id: %d\n",id); + return -1; + } + + return streams.get(id).len; + + } + public void file_seek(int id,int bytes) { + + if (!streams.containsKey(id)) { + System.out.printf("file_get_size: Invalid file id: %d\n",id); + return; + } + //seek sucks + AssetData ad = streams.get(id); + if (bytes>ad.len) + bytes=ad.len; + if (bytes<0) + bytes=0; + + try { + + if (bytes > (int)ad.pos) { + int todo=bytes-(int)ad.pos; + while(todo>0) { + todo-=ad.is.skip(todo); + } + ad.pos=bytes; + } else if (bytes<(int)ad.pos) { + + ad.is=am.open(ad.path); + + ad.pos=bytes; + int todo=bytes; + while(todo>0) { + todo-=ad.is.skip(todo); + } + } + + ad.eof=false; + } catch (IOException e) { + + System.out.printf("Exception on file_seek: %s\n",e); + return; + } + + + } + + public int file_tell(int id) { + + if (!streams.containsKey(id)) { + System.out.printf("file_read: Can't tell eof for invalid file id: %d\n",id); + return 0; + } + + AssetData ad = streams.get(id); + return ad.pos; + } + public boolean file_eof(int id) { + + if (!streams.containsKey(id)) { + System.out.printf("file_read: Can't check eof for invalid file id: %d\n",id); + return false; + } + + AssetData ad = streams.get(id); + return ad.eof; + } + + public byte[] file_read(int id, int bytes) { + + if (!streams.containsKey(id)) { + System.out.printf("file_read: Can't read invalid file id: %d\n",id); + return new byte[0]; + } + + + AssetData ad = streams.get(id); + + if (ad.pos + bytes > ad.len) { + + bytes=ad.len-ad.pos; + ad.eof=true; + } + + + if (bytes==0) { + + return new byte[0]; + } + + + + byte[] buf1=new byte[bytes]; + int r=0; + try { + r = ad.is.read(buf1); + } catch (IOException e) { + + System.out.printf("Exception on file_read: %s\n",e); + return new byte[bytes]; + } + + if (r==0) { + return new byte[0]; + } + + ad.pos+=r; + + if (r<bytes) { + + byte[] buf2=new byte[r]; + for(int i=0;i<r;i++) + buf2[i]=buf1[i]; + return buf2; + } else { + + return buf1; + } + + } + + public void file_close(int id) { + + if (!streams.containsKey(id)) { + System.out.printf("file_close: Can't close invalid file id: %d\n",id); + return; + } + + streams.remove(id); + + } + + + ///////////////////////// + /// DIRECTORIES + ///////////////////////// + + + class AssetDir { + + public String[] files; + public int current; + } + + public int last_dir_id=1; + + HashMap<Integer,AssetDir> dirs; + + public int dir_open(String path) { + + AssetDir ad = new AssetDir(); + ad.current=0; + + try { + ad.files = am.list(path); + } catch (IOException e) { + + System.out.printf("Exception on dir_open: %s\n",e); + return -1; + } + + ++last_dir_id; + dirs.put(last_dir_id,ad); + + return last_dir_id; + + } + + public String dir_next(int id) { + + if (!dirs.containsKey(id)) { + System.out.printf("dir_next: invalid dir id: %d\n",id); + return ""; + } + + AssetDir ad = dirs.get(id); + if (ad.current>=ad.files.length) + return ""; + String r = ad.files[ad.current]; + ad.current++; + return r; + + } + + public void dir_close(int id) { + + if (!dirs.containsKey(id)) { + System.out.printf("dir_close: invalid dir id: %d\n",id); + return; + } + + dirs.remove(id); + } + + + + GodotIO(Activity p_activity) { + + am=p_activity.getAssets(); + activity=p_activity; + streams=new HashMap<Integer,AssetData>(); + dirs=new HashMap<Integer,AssetDir>(); + + + } + + + ///////////////////////// + // AUDIO + ///////////////////////// + + private Object buf; + private Thread mAudioThread; + private AudioTrack mAudioTrack; + + public Object audioInit(int sampleRate, int desiredFrames) { + int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_STEREO; + int audioFormat = AudioFormat.ENCODING_PCM_16BIT; + int frameSize = 4; + + System.out.printf("audioInit: initializing audio:\n"); + + //Log.v("Godot", "Godot audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + ((float)sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer"); + + // Let the user pick a larger buffer if they really want -- but ye + // gods they probably shouldn't, the minimums are horrifyingly high + // latency already + desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize); + + mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, + channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM); + + audioStartThread(); + + //Log.v("Godot", "Godot audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer"); + + buf = new short[desiredFrames * 2]; + return buf; + } + + public void audioStartThread() { + mAudioThread = new Thread(new Runnable() { + public void run() { + mAudioTrack.play(); + GodotLib.audio(); + } + }); + + // I'd take REALTIME if I could get it! + mAudioThread.setPriority(Thread.MAX_PRIORITY); + mAudioThread.start(); + } + + public void audioWriteShortBuffer(short[] buffer) { + for (int i = 0; i < buffer.length; ) { + int result = mAudioTrack.write(buffer, i, buffer.length - i); + if (result > 0) { + i += result; + } else if (result == 0) { + try { + Thread.sleep(1); + } catch(InterruptedException e) { + // Nom nom + } + } else { + Log.w("Godot", "Godot audio: error return from write(short)"); + return; + } + } + } + + + + public void audioQuit() { + if (mAudioThread != null) { + try { + mAudioThread.join(); + } catch(Exception e) { + Log.v("Godot", "Problem stopping audio thread: " + e); + } + mAudioThread = null; + + //Log.v("Godot", "Finished waiting for audio thread"); + } + + if (mAudioTrack != null) { + mAudioTrack.stop(); + mAudioTrack = null; + } + } + + public void audioPause(boolean p_pause) { + + if (p_pause) + mAudioTrack.pause(); + else + mAudioTrack.play(); + } + + ///////////////////////// + // MISCELANEOUS OS IO + ///////////////////////// + + + + public int openURI(String p_uri) { + + try { + Log.v("MyApp", "TRYING TO OPEN URI: " + p_uri); + Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(p_uri)); + activity.startActivity(myIntent); + return 0; + } catch (ActivityNotFoundException e) { + + return 1; + } + } + + public String getDataDir() { + + return activity.getFilesDir().getAbsolutePath(); + } + + public String getLocale() { + + return Locale.getDefault().toString(); + } + + public String getModel() { + return Build.MODEL; + } + + public boolean needsReloadHooks() { + + return android.os.Build.VERSION.SDK_INT < 11; + } + + public void showKeyboard(String p_existing_text) { + + InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE); + inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + }; + + public void hideKeyboard() { + + InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE); + inputMgr.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + }; + + public void setScreenOrientation(int p_orientation) { + + switch(p_orientation) { + + case SCREEN_LANDSCAPE: { + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } break; + case SCREEN_PORTRAIT: { + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } break; + case SCREEN_REVERSE_LANDSCAPE: { + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); + } break; + case SCREEN_REVERSE_PORTRAIT: { + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); + } break; + case SCREEN_SENSOR_LANDSCAPE: { + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); + } break; + case SCREEN_SENSOR_PORTRAIT: { + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); + } break; + case SCREEN_SENSOR: { + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); + } break; + + } + }; + + protected static final String PREFS_FILE = "device_id.xml"; + protected static final String PREFS_DEVICE_ID = "device_id"; + + public static String unique_id=""; + public String getUniqueID() { + + return unique_id; + } + +} diff --git a/platform/android/java/src/com/android/godot/GodotLib.java b/platform/android/java/src/com/android/godot/GodotLib.java new file mode 100644 index 000000000..8d002c5eb --- /dev/null +++ b/platform/android/java/src/com/android/godot/GodotLib.java @@ -0,0 +1,63 @@ +/*************************************************************************/ +/* GodotLib.java */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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. */ +/*************************************************************************/ +package com.android.godot; + +// Wrapper for native library + +public class GodotLib { + + + public static GodotIO io; + + static { + System.loadLibrary("godot_android"); + } + + /** + * @param width the current view width + * @param height the current view height + */ + + public static native void initialize(Godot p_instance,boolean need_reload_hook); + public static native void resize(int width, int height,boolean reload); + public static native void newcontext(); + public static native void quit(); + public static native void step(); + public static native void touch(int what,int pointer,int howmany, int[] arr); + public static native void accelerometer(float x, float y, float z); + public static native void key(int p_unicode_char, boolean p_pressed); + public static native void focusin(); + public static native void focusout(); + public static native void audio(); + public static native void singleton(String p_name,Object p_object); + public static native void method(String p_sname,String p_name,String p_ret,String[] p_params); + public static native String getGlobal(String p_key); + public static native void callobject(int p_ID, String p_method, Object[] p_params); + +} diff --git a/platform/android/java/src/com/android/godot/GodotView.java b/platform/android/java/src/com/android/godot/GodotView.java new file mode 100644 index 000000000..093757bfb --- /dev/null +++ b/platform/android/java/src/com/android/godot/GodotView.java @@ -0,0 +1,378 @@ +/*************************************************************************/ +/* GodotView.java */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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. */ +/*************************************************************************/ +package com.android.godot; +import android.content.Context; +import android.graphics.PixelFormat; +import android.opengl.GLSurfaceView; +import android.util.AttributeSet; +import android.util.Log; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.content.ContextWrapper; + +import java.io.File; +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLContext; +import javax.microedition.khronos.egl.EGLDisplay; +import javax.microedition.khronos.opengles.GL10; + +/** + * A simple GLSurfaceView sub-class that demonstrate how to perform + * OpenGL ES 2.0 rendering into a GL Surface. Note the following important + * details: + * + * - The class must use a custom context factory to enable 2.0 rendering. + * See ContextFactory class definition below. + * + * - The class must use a custom EGLConfigChooser to be able to select + * an EGLConfig that supports 2.0. This is done by providing a config + * specification to eglChooseConfig() that has the attribute + * EGL10.ELG_RENDERABLE_TYPE containing the EGL_OPENGL_ES2_BIT flag + * set. See ConfigChooser class definition below. + * + * - The class must select the surface's format, then choose an EGLConfig + * that matches it exactly (with regards to red/green/blue/alpha channels + * bit depths). Failure to do so would result in an EGL_BAD_MATCH error. + */ +class GodotView extends GLSurfaceView { + private static String TAG = "GodotView"; + private static final boolean DEBUG = false; + private static Context ctx; + + private static GodotIO io; + private static boolean firsttime=true; + private static boolean use_gl2=false; + + private Godot activity; + + public GodotView(Context context,GodotIO p_io,boolean p_use_gl2, Godot p_activity) { + super(context); + ctx=context; + io=p_io; + use_gl2=p_use_gl2; + + activity = p_activity; + + if (!p_io.needsReloadHooks()) { + //will only work on SDK 11+!! + setPreserveEGLContextOnPause(true); + } + + init(false, 16, 0); + } + + public GodotView(Context context, boolean translucent, int depth, int stencil) { + super(context); + init(translucent, depth, stencil); + } + + @Override public boolean onTouchEvent (MotionEvent event) { + + return activity.gotTouchEvent(event); + }; + + private void init(boolean translucent, int depth, int stencil) { + + /* By default, GLSurfaceView() creates a RGB_565 opaque surface. + * If we want a translucent one, we should change the surface's + * format here, using PixelFormat.TRANSLUCENT for GL Surfaces + * is interpreted as any 32-bit surface with alpha by SurfaceFlinger. + */ + if (translucent) { + this.getHolder().setFormat(PixelFormat.TRANSLUCENT); + } + + /* Setup the context factory for 2.0 rendering. + * See ContextFactory class definition below + */ + setEGLContextFactory(new ContextFactory()); + + /* We need to choose an EGLConfig that matches the format of + * our surface exactly. This is going to be done in our + * custom config chooser. See ConfigChooser class definition + * below. + */ + setEGLConfigChooser( translucent ? + new ConfigChooser(8, 8, 8, 8, depth, stencil) : + new ConfigChooser(5, 6, 5, 0, depth, stencil) ); + + /* Set the renderer responsible for frame rendering */ + setRenderer(new Renderer()); + } + + private static class ContextFactory implements GLSurfaceView.EGLContextFactory { + private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098; + public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) { + if (use_gl2) + Log.w(TAG, "creating OpenGL ES 2.0 context :"); + else + Log.w(TAG, "creating OpenGL ES 1.1 context :"); + + checkEglError("Before eglCreateContext", egl); + int[] attrib_list2 = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; + EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, use_gl2?attrib_list2:null); + checkEglError("After eglCreateContext", egl); + return context; + } + + public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) { + egl.eglDestroyContext(display, context); + } + } + + private static void checkEglError(String prompt, EGL10 egl) { + int error; + while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) { + Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error)); + } + } + + private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser { + + public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) { + mRedSize = r; + mGreenSize = g; + mBlueSize = b; + mAlphaSize = a; + mDepthSize = depth; + mStencilSize = stencil; + } + + /* This EGL config specification is used to specify 2.0 rendering. + * We use a minimum size of 4 bits for red/green/blue, but will + * perform actual matching in chooseConfig() below. + */ + private static int EGL_OPENGL_ES2_BIT = 4; + private static int[] s_configAttribs2 = + { + EGL10.EGL_RED_SIZE, 4, + EGL10.EGL_GREEN_SIZE, 4, + EGL10.EGL_BLUE_SIZE, 4, + // EGL10.EGL_DEPTH_SIZE, 16, + // EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE, + EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL10.EGL_NONE + }; + private static int[] s_configAttribs = + { + EGL10.EGL_RED_SIZE, 4, + EGL10.EGL_GREEN_SIZE, 4, + EGL10.EGL_BLUE_SIZE, 4, + // EGL10.EGL_DEPTH_SIZE, 16, + // EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE, + EGL10.EGL_NONE + }; + + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { + + /* Get the number of minimally matching EGL configurations + */ + int[] num_config = new int[1]; + egl.eglChooseConfig(display, use_gl2?s_configAttribs2:s_configAttribs, null, 0, num_config); + + int numConfigs = num_config[0]; + + if (numConfigs <= 0) { + throw new IllegalArgumentException("No configs match configSpec"); + } + + /* Allocate then read the array of minimally matching EGL configs + */ + EGLConfig[] configs = new EGLConfig[numConfigs]; + egl.eglChooseConfig(display, use_gl2?s_configAttribs2:s_configAttribs, configs, numConfigs, num_config); + + if (DEBUG) { + printConfigs(egl, display, configs); + } + /* Now return the "best" one + */ + return chooseConfig(egl, display, configs); + } + + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, + EGLConfig[] configs) { + for(EGLConfig config : configs) { + int d = findConfigAttrib(egl, display, config, + EGL10.EGL_DEPTH_SIZE, 0); + int s = findConfigAttrib(egl, display, config, + EGL10.EGL_STENCIL_SIZE, 0); + + // We need at least mDepthSize and mStencilSize bits + if (d < mDepthSize || s < mStencilSize) + continue; + + // We want an *exact* match for red/green/blue/alpha + int r = findConfigAttrib(egl, display, config, + EGL10.EGL_RED_SIZE, 0); + int g = findConfigAttrib(egl, display, config, + EGL10.EGL_GREEN_SIZE, 0); + int b = findConfigAttrib(egl, display, config, + EGL10.EGL_BLUE_SIZE, 0); + int a = findConfigAttrib(egl, display, config, + EGL10.EGL_ALPHA_SIZE, 0); + + if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize) + return config; + } + return null; + } + + private int findConfigAttrib(EGL10 egl, EGLDisplay display, + EGLConfig config, int attribute, int defaultValue) { + + if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { + return mValue[0]; + } + return defaultValue; + } + + private void printConfigs(EGL10 egl, EGLDisplay display, + EGLConfig[] configs) { + int numConfigs = configs.length; + Log.w(TAG, String.format("%d configurations", numConfigs)); + for (int i = 0; i < numConfigs; i++) { + Log.w(TAG, String.format("Configuration %d:\n", i)); + printConfig(egl, display, configs[i]); + } + } + + private void printConfig(EGL10 egl, EGLDisplay display, + EGLConfig config) { + int[] attributes = { + EGL10.EGL_BUFFER_SIZE, + EGL10.EGL_ALPHA_SIZE, + EGL10.EGL_BLUE_SIZE, + EGL10.EGL_GREEN_SIZE, + EGL10.EGL_RED_SIZE, + EGL10.EGL_DEPTH_SIZE, + EGL10.EGL_STENCIL_SIZE, + EGL10.EGL_CONFIG_CAVEAT, + EGL10.EGL_CONFIG_ID, + EGL10.EGL_LEVEL, + EGL10.EGL_MAX_PBUFFER_HEIGHT, + EGL10.EGL_MAX_PBUFFER_PIXELS, + EGL10.EGL_MAX_PBUFFER_WIDTH, + EGL10.EGL_NATIVE_RENDERABLE, + EGL10.EGL_NATIVE_VISUAL_ID, + EGL10.EGL_NATIVE_VISUAL_TYPE, + 0x3030, // EGL10.EGL_PRESERVED_RESOURCES, + EGL10.EGL_SAMPLES, + EGL10.EGL_SAMPLE_BUFFERS, + EGL10.EGL_SURFACE_TYPE, + EGL10.EGL_TRANSPARENT_TYPE, + EGL10.EGL_TRANSPARENT_RED_VALUE, + EGL10.EGL_TRANSPARENT_GREEN_VALUE, + EGL10.EGL_TRANSPARENT_BLUE_VALUE, + 0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB, + 0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA, + 0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL, + 0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL, + EGL10.EGL_LUMINANCE_SIZE, + EGL10.EGL_ALPHA_MASK_SIZE, + EGL10.EGL_COLOR_BUFFER_TYPE, + EGL10.EGL_RENDERABLE_TYPE, + 0x3042 // EGL10.EGL_CONFORMANT + }; + String[] names = { + "EGL_BUFFER_SIZE", + "EGL_ALPHA_SIZE", + "EGL_BLUE_SIZE", + "EGL_GREEN_SIZE", + "EGL_RED_SIZE", + "EGL_DEPTH_SIZE", + "EGL_STENCIL_SIZE", + "EGL_CONFIG_CAVEAT", + "EGL_CONFIG_ID", + "EGL_LEVEL", + "EGL_MAX_PBUFFER_HEIGHT", + "EGL_MAX_PBUFFER_PIXELS", + "EGL_MAX_PBUFFER_WIDTH", + "EGL_NATIVE_RENDERABLE", + "EGL_NATIVE_VISUAL_ID", + "EGL_NATIVE_VISUAL_TYPE", + "EGL_PRESERVED_RESOURCES", + "EGL_SAMPLES", + "EGL_SAMPLE_BUFFERS", + "EGL_SURFACE_TYPE", + "EGL_TRANSPARENT_TYPE", + "EGL_TRANSPARENT_RED_VALUE", + "EGL_TRANSPARENT_GREEN_VALUE", + "EGL_TRANSPARENT_BLUE_VALUE", + "EGL_BIND_TO_TEXTURE_RGB", + "EGL_BIND_TO_TEXTURE_RGBA", + "EGL_MIN_SWAP_INTERVAL", + "EGL_MAX_SWAP_INTERVAL", + "EGL_LUMINANCE_SIZE", + "EGL_ALPHA_MASK_SIZE", + "EGL_COLOR_BUFFER_TYPE", + "EGL_RENDERABLE_TYPE", + "EGL_CONFORMANT" + }; + int[] value = new int[1]; + for (int i = 0; i < attributes.length; i++) { + int attribute = attributes[i]; + String name = names[i]; + if ( egl.eglGetConfigAttrib(display, config, attribute, value)) { + Log.w(TAG, String.format(" %s: %d\n", name, value[0])); + } else { + // Log.w(TAG, String.format(" %s: failed\n", name)); + while (egl.eglGetError() != EGL10.EGL_SUCCESS); + } + } + } + + // Subclasses can adjust these values: + protected int mRedSize; + protected int mGreenSize; + protected int mBlueSize; + protected int mAlphaSize; + protected int mDepthSize; + protected int mStencilSize; + private int[] mValue = new int[1]; + } + + private static class Renderer implements GLSurfaceView.Renderer { + + + public void onDrawFrame(GL10 gl) { + GodotLib.step(); + } + + public void onSurfaceChanged(GL10 gl, int width, int height) { + + GodotLib.resize(width, height,!firsttime); + firsttime=false; + } + + public void onSurfaceCreated(GL10 gl, EGLConfig config) { + GodotLib.newcontext(); + } + } +} diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp new file mode 100644 index 000000000..9c5003cb1 --- /dev/null +++ b/platform/android/java_glue.cpp @@ -0,0 +1,1153 @@ +/*************************************************************************/ +/* java_glue.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef ANDROID_NATIVE_ACTIVITY + +#include "java_glue.h" +#include "os_android.h" +#include "main/main.h" +#include <unistd.h> +#include "file_access_jandroid.h" +#include "dir_access_jandroid.h" +#include "audio_driver_jandroid.h" +#include "globals.h" +#include "thread_jandroid.h" +#include "core/os/keyboard.h" +static OS_Android *os_android=NULL; + + +jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_arg, bool force_jobject = false) { + + jvalue v; + + switch(p_type) { + + case Variant::BOOL: { + + if (force_jobject) { + jclass bclass = env->FindClass("java/lang/Boolean"); + jmethodID ctor = env->GetMethodID(bclass, "<init>", "(Z)V"); + jvalue val; + val.z = (bool)(*p_arg); + jobject obj = env->NewObjectA(bclass, ctor, &val); + v.l = obj; + } else { + v.z=*p_arg; + }; + } break; + case Variant::INT: { + + if (force_jobject) { + + jclass bclass = env->FindClass("java/lang/Integer"); + jmethodID ctor = env->GetMethodID(bclass, "<init>", "(I)V"); + jvalue val; + val.i = (int)(*p_arg); + jobject obj = env->NewObjectA(bclass, ctor, &val); + v.l = obj; + + } else { + v.i=*p_arg; + }; + } break; + case Variant::REAL: { + + if (force_jobject) { + + jclass bclass = env->FindClass("java/lang/Double"); + jmethodID ctor = env->GetMethodID(bclass, "<init>", "(D)V"); + jvalue val; + val.d = (double)(*p_arg); + jobject obj = env->NewObjectA(bclass, ctor, &val); + v.l = obj; + + } else { + v.f=*p_arg; + }; + } break; + case Variant::STRING: { + + String s = *p_arg; + jstring jStr = env->NewStringUTF(s.utf8().get_data()); + v.l=jStr; + } break; + case Variant::STRING_ARRAY: { + + DVector<String> sarray = *p_arg; + jobjectArray arr = env->NewObjectArray(sarray.size(),env->FindClass("java/lang/String"),env->NewStringUTF("")); + + for(int j=0;j<sarray.size();j++) { + + env->SetObjectArrayElement(arr,j,env->NewStringUTF( sarray[j].utf8().get_data() )); + } + v.l=arr; + + } break; + + case Variant::DICTIONARY: { + + Dictionary dict = *p_arg; + jclass dclass = env->FindClass("com/android/godot/Dictionary"); + jmethodID ctor = env->GetMethodID(dclass, "<init>", "()V"); + jobject jdict = env->NewObject(dclass, ctor); + + Array keys = dict.keys(); + + jobjectArray jkeys = env->NewObjectArray(keys.size(), env->FindClass("java/lang/String"), env->NewStringUTF("")); + for (int j=0; j<keys.size(); j++) { + env->SetObjectArrayElement(jkeys, j, env->NewStringUTF(String(keys[j]).utf8().get_data())); + }; + + jmethodID set_keys = env->GetMethodID(dclass, "set_keys", "([Ljava/lang/String;)V"); + jvalue val; + val.l = jkeys; + env->CallVoidMethodA(jdict, set_keys, &val); + + jobjectArray jvalues = env->NewObjectArray(keys.size(), env->FindClass("java/lang/Object"), NULL); + + for (int j=0; j<keys.size(); j++) { + Variant var = dict[keys[j]]; + val = _variant_to_jvalue(env, var.get_type(), &var, true); + env->SetObjectArrayElement(jvalues, j, val.l); + }; + + jmethodID set_values = env->GetMethodID(dclass, "set_values", "([Ljava/lang/Object;)V"); + val.l = jvalues; + env->CallVoidMethodA(jdict, set_values, &val); + + v.l = jdict; + } break; + + case Variant::INT_ARRAY: { + + DVector<int> array = *p_arg; + jintArray arr = env->NewIntArray(array.size()); + DVector<int>::Read r = array.read(); + env->SetIntArrayRegion(arr,0,array.size(),r.ptr()); + v.l=arr; + + } break; + case Variant::REAL_ARRAY: { + + DVector<float> array = *p_arg; + jfloatArray arr = env->NewFloatArray(array.size()); + DVector<float>::Read r = array.read(); + env->SetFloatArrayRegion(arr,0,array.size(),r.ptr()); + v.l=arr; + + } break; + default: { + + v.i = 0; + } break; + + } + return v; +}; + +String _get_class_name(JNIEnv * env, jclass cls, bool* array) { + + jclass cclass = env->FindClass("java/lang/Class"); + jmethodID getName = env->GetMethodID(cclass, "getName", "()Ljava/lang/String;"); + jstring clsName=(jstring) env->CallObjectMethod(cls, getName); + + if (array) { + jmethodID isArray = env->GetMethodID(cclass, "isArray", "()Z"); + jboolean isarr = env->CallBooleanMethod(cls, isArray); + (*array) = isarr ? true : false; + } + + return env->GetStringUTFChars( clsName, NULL ); +}; + + +Variant _jobject_to_variant(JNIEnv * env, jobject obj) { + + jclass c = env->GetObjectClass(obj); + bool array; + String name = _get_class_name(env, c, &array); + //print_line("name is " + name + ", array "+Variant(array)); + + if (name == "java.lang.String") { + + return String::utf8(env->GetStringUTFChars( (jstring)obj, NULL )); + }; + + + if (name == "[Ljava.lang.String;") { + + jobjectArray arr = (jobjectArray)obj; + int stringCount = env->GetArrayLength(arr); + //print_line("String array! " + String::num(stringCount)); + DVector<String> sarr; + + for (int i=0; i<stringCount; i++) { + jstring string = (jstring) env->GetObjectArrayElement(arr, i); + const char *rawString = env->GetStringUTFChars(string, 0); + sarr.push_back(String(rawString)); + } + + return sarr; + }; + + if (name == "java.lang.Boolean") { + + jmethodID boolValue = env->GetMethodID(c, "booleanValue", "()Z"); + bool ret = env->CallBooleanMethod(obj, boolValue); + return ret; + }; + + if (name == "java.lang.Integer") { + + jclass nclass = env->FindClass("java/lang/Number"); + jmethodID intValue = env->GetMethodID(nclass, "intValue", "()I"); + int ret = env->CallIntMethod(obj, intValue); + return ret; + }; + + if (name == "[I") { + + jintArray arr = (jintArray)obj; + int fCount = env->GetArrayLength(arr); + DVector<int> sarr; + sarr.resize(fCount); + + DVector<int>::Write w = sarr.write(); + env->GetIntArrayRegion(arr,0,fCount,w.ptr()); + w = DVector<int>::Write(); + return sarr; + }; + + if (name == "java.lang.Float" || name == "java.lang.Double") { + + jclass nclass = env->FindClass("java/lang/Number"); + jmethodID doubleValue = env->GetMethodID(nclass, "doubleValue", "()D"); + double ret = env->CallDoubleMethod(obj, doubleValue); + return ret; + }; + + if (name == "[D") { + + jdoubleArray arr = (jdoubleArray)obj; + int fCount = env->GetArrayLength(arr); + RealArray sarr; + sarr.resize(fCount); + + RealArray::Write w = sarr.write(); + + for (int i=0; i<fCount; i++) { + + double n; + env->GetDoubleArrayRegion(arr, i, 1, &n); + w.ptr()[i] = n; + + }; + return sarr; + }; + + if (name == "[F") { + + jfloatArray arr = (jfloatArray)obj; + int fCount = env->GetArrayLength(arr); + RealArray sarr; + sarr.resize(fCount); + + + RealArray::Write w = sarr.write(); + + for (int i=0; i<fCount; i++) { + + float n; + env->GetFloatArrayRegion(arr, i, 1, &n); + w.ptr()[i] = n; + + }; + return sarr; + }; + + + if (name == "[Ljava.lang.Object;") { + + jobjectArray arr = (jobjectArray)obj; + int objCount = env->GetArrayLength(arr); + Array varr; + + for (int i=0; i<objCount; i++) { + jobject jobj = env->GetObjectArrayElement(arr, i); + Variant v = _jobject_to_variant(env, jobj); + varr.push_back(v); + } + + return varr; + }; + + if (name == "com.android.godot.Dictionary") { + + Dictionary ret; + jclass oclass = c; + jmethodID get_keys = env->GetMethodID(oclass, "get_keys", "()[Ljava/lang/String;"); + jobjectArray arr = (jobjectArray)env->CallObjectMethod(obj, get_keys); + + StringArray keys = _jobject_to_variant(env, arr); + + jmethodID get_values = env->GetMethodID(oclass, "get_values", "()[Ljava/lang/Object;"); + arr = (jobjectArray)env->CallObjectMethod(obj, get_values); + + Array vals = _jobject_to_variant(env, arr); + + //print_line("adding " + String::num(keys.size()) + " to Dictionary!"); + for (int i=0; i<keys.size(); i++) { + + ret[keys[i]] = vals[i]; + }; + + return ret; + }; + + return Variant(); +}; + +class JNISingleton : public Object { + + OBJ_TYPE( JNISingleton, Object ); + + + struct MethodData { + + + jmethodID method; + Variant::Type ret_type; + Vector<Variant::Type> argtypes; + }; + + jobject instance; + Map<StringName,MethodData> method_map; + +public: + + virtual Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error) { + + //print_line("attempt to call "+String(p_method)); + + r_error.error=Variant::CallError::CALL_OK; + + Map<StringName,MethodData >::Element *E=method_map.find(p_method); + if (!E) { + + print_line("no exists"); + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); + } + + + int ac = E->get().argtypes.size(); + if (ac<p_argcount) { + + print_line("fewargs"); + r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument=ac; + return Variant(); + } + + if (ac>p_argcount) { + + print_line("manyargs"); + r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument=ac; + return Variant(); + } + + + + for(int i=0;i<p_argcount;i++) { + + if (!Variant::can_convert(p_args[i]->get_type(),E->get().argtypes[i])) { + + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=i; + r_error.expected=E->get().argtypes[i]; + } + } + + + jvalue *v=NULL; + + if (p_argcount) { + + v=(jvalue*)alloca( sizeof(jvalue)*p_argcount ); + } + + JNIEnv *env = ThreadAndroid::get_env(); + + //print_line("argcount "+String::num(p_argcount)); + for(int i=0;i<p_argcount;i++) { + + v[i] = _variant_to_jvalue(env, E->get().argtypes[i], p_args[i]); + } + + //print_line("calling method!!"); + + Variant ret; + + switch(E->get().ret_type) { + + case Variant::NIL: { + + + //print_line("call void"); + env->CallVoidMethodA(instance,E->get().method,v); + } break; + case Variant::BOOL: { + + ret = env->CallBooleanMethodA(instance,E->get().method,v); + //print_line("call bool"); + } break; + case Variant::INT: { + + ret = env->CallIntMethodA(instance,E->get().method,v); + //print_line("call int"); + } break; + case Variant::REAL: { + + ret = env->CallFloatMethodA(instance,E->get().method,v); + } break; + case Variant::STRING: { + + jobject o = env->CallObjectMethodA(instance,E->get().method,v); + String singname = env->GetStringUTFChars((jstring)o, NULL ); + } break; + case Variant::STRING_ARRAY: { + + jobjectArray arr = (jobjectArray)env->CallObjectMethodA(instance,E->get().method,v); + + ret = _jobject_to_variant(env, arr); + + } break; + case Variant::INT_ARRAY: { + + jintArray arr = (jintArray)env->CallObjectMethodA(instance,E->get().method,v); + + int fCount = env->GetArrayLength(arr); + DVector<int> sarr; + sarr.resize(fCount); + + DVector<int>::Write w = sarr.write(); + env->GetIntArrayRegion(arr,0,fCount,w.ptr()); + w = DVector<int>::Write(); + ret=sarr; + } break; + case Variant::REAL_ARRAY: { + + jfloatArray arr = (jfloatArray)env->CallObjectMethodA(instance,E->get().method,v); + + int fCount = env->GetArrayLength(arr); + DVector<float> sarr; + sarr.resize(fCount); + + DVector<float>::Write w = sarr.write(); + env->GetFloatArrayRegion(arr,0,fCount,w.ptr()); + w = DVector<float>::Write(); + ret=sarr; + } break; + + case Variant::DICTIONARY: { + + //print_line("call dictionary"); + jobject obj = env->CallObjectMethodA(instance, E->get().method, v); + ret = _jobject_to_variant(env, obj); + + } break; + default: { + + + print_line("failure.."); + ERR_FAIL_V(Variant()); + } break; + } + + //print_line("success"); + + return ret; + } + + + jobject get_instance() const { + + return instance; + } + void set_instance(jobject p_instance) { + + instance=p_instance; + } + + + void add_method(const StringName& p_name, jmethodID p_method,const Vector<Variant::Type>& p_args, Variant::Type p_ret_type) { + + MethodData md; + md.method=p_method; + md.argtypes=p_args; + md.ret_type=p_ret_type; + method_map[p_name]=md; + + } + + + JNISingleton() {} + +}; + + +struct TST { + + int a; + TST() { + + a=5; + } +}; + +TST tst; + +struct JAndroidPointerEvent { + + Vector<OS_Android::TouchPos> points; + int pointer; + int what; +}; + +static List<JAndroidPointerEvent> pointer_events; +static List<InputEvent> key_events; +static bool initialized=false; +static Mutex *input_mutex=NULL; +static Mutex *suspend_mutex=NULL; +static int step=0; +static bool resized=false; +static bool resized_reload=false; +static bool quit_request=false; +static Size2 new_size; +static Vector3 accelerometer; +static HashMap<String,JNISingleton*> jni_singletons; +static jobject godot_io; + +typedef void (*GFXInitFunc)(void *ud,bool gl2); + +static jmethodID _on_video_init=0; +static jobject _godot_instance; + +static jmethodID _openURI=0; +static jmethodID _getDataDir=0; +static jmethodID _getLocale=0; +static jmethodID _getModel=0; +static jmethodID _showKeyboard=0; +static jmethodID _hideKeyboard=0; +static jmethodID _setScreenOrientation=0; +static jmethodID _getUniqueID=0; + + +static void _gfx_init_func(void* ud, bool gl2) { + +} + + +static int _open_uri(const String& p_uri) { + + JNIEnv *env = ThreadAndroid::get_env(); + jstring jStr = env->NewStringUTF(p_uri.utf8().get_data()); + return env->CallIntMethod(godot_io,_openURI,jStr) ; +} + +static String _get_data_dir() { + + JNIEnv *env = ThreadAndroid::get_env(); + jstring s =(jstring)env->CallObjectMethod(godot_io,_getDataDir); + return String(env->GetStringUTFChars( s, NULL )); +} + +static String _get_locale() { + + JNIEnv *env = ThreadAndroid::get_env(); + jstring s =(jstring)env->CallObjectMethod(godot_io,_getLocale); + return String(env->GetStringUTFChars( s, NULL )); +} + +static String _get_model() { + + JNIEnv *env = ThreadAndroid::get_env(); + jstring s =(jstring)env->CallObjectMethod(godot_io,_getModel); + return String(env->GetStringUTFChars( s, NULL )); +} + +static String _get_unique_id() { + + JNIEnv *env = ThreadAndroid::get_env(); + jstring s =(jstring)env->CallObjectMethod(godot_io,_getUniqueID); + return String(env->GetStringUTFChars( s, NULL )); +} + +static void _show_vk(const String& p_existing) { + + JNIEnv* env = ThreadAndroid::get_env(); + jstring jStr = env->NewStringUTF(p_existing.utf8().get_data()); + env->CallVoidMethod(godot_io, _showKeyboard, jStr); +}; + +static void _set_screen_orient(int p_orient) { + + JNIEnv* env = ThreadAndroid::get_env(); + env->CallVoidMethod(godot_io, _setScreenOrientation, p_orient ); +}; + +static void _hide_vk() { + + JNIEnv* env = ThreadAndroid::get_env(); + env->CallVoidMethod(godot_io, _hideKeyboard); +}; + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook) { + + __android_log_print(ANDROID_LOG_INFO,"godot","**INIT EVENT! - %p\n",env); + + + initialized=true; + _godot_instance=activity; + + JavaVM *jvm; + env->GetJavaVM(&jvm); + + + __android_log_print(ANDROID_LOG_INFO,"godot","***************** HELLO FROM JNI!!!!!!!!"); + + { + //setup IO Object + + jclass cls = env->FindClass("com/android/godot/Godot"); + if (cls) { + + cls=(jclass)env->NewGlobalRef(cls); + __android_log_print(ANDROID_LOG_INFO,"godot","*******CLASS FOUND!!!"); + } + + __android_log_print(ANDROID_LOG_INFO,"godot","STEP2, %p",cls); + jfieldID fid = env->GetStaticFieldID(cls, "io", "Lcom/android/godot/GodotIO;"); + __android_log_print(ANDROID_LOG_INFO,"godot","STEP3 %i",fid); + jobject ob = env->GetStaticObjectField(cls,fid); + __android_log_print(ANDROID_LOG_INFO,"godot","STEP4, %p",ob); + jobject gob = env->NewGlobalRef(ob); + + __android_log_print(ANDROID_LOG_INFO,"godot","STEP4.5, %p",gob); + godot_io=gob; + + _on_video_init = env->GetMethodID(cls, "onVideoInit", "(Z)V"); + + jclass clsio = env->FindClass("com/android/godot/Godot"); + if (cls) { + jclass c = env->GetObjectClass(gob); + _openURI = env->GetMethodID(c,"openURI","(Ljava/lang/String;)I"); + _getDataDir = env->GetMethodID(c,"getDataDir","()Ljava/lang/String;"); + _getLocale = env->GetMethodID(c,"getLocale","()Ljava/lang/String;"); + _getModel = env->GetMethodID(c,"getModel","()Ljava/lang/String;"); + _getUniqueID = env->GetMethodID(c,"getUniqueID","()Ljava/lang/String;"); + _showKeyboard = env->GetMethodID(c,"showKeyboard","(Ljava/lang/String;)V"); + _hideKeyboard = env->GetMethodID(c,"hideKeyboard","()V"); + _setScreenOrientation = env->GetMethodID(c,"setScreenOrientation","(I)V"); + } + + ThreadAndroid::make_default(jvm); + FileAccessJAndroid::setup(gob); + DirAccessJAndroid::setup(gob); + AudioDriverAndroid::setup(gob); + } + + + + os_android = new OS_Android(_gfx_init_func,env,_open_uri,_get_data_dir,_get_locale, _get_model,_show_vk, _hide_vk,_set_screen_orient,_get_unique_id); + os_android->set_need_reload_hooks(p_need_reload_hook); + + char wd[500]; + getcwd(wd,500); + + __android_log_print(ANDROID_LOG_INFO,"godot","test construction %i\n",tst.a); + __android_log_print(ANDROID_LOG_INFO,"godot","running from dir %s\n",wd); + + __android_log_print(ANDROID_LOG_INFO,"godot","**SETUP"); + + +#if 0 + char *args[]={"-test","render",NULL}; + __android_log_print(ANDROID_LOG_INFO,"godot","pre asdasd setup..."); + Error err = Main::setup("apk",2,args,false); +#else + Error err = Main::setup("apk",0,NULL,false); +#endif + + if (err!=OK) { + __android_log_print(ANDROID_LOG_INFO,"godot","*****UNABLE TO SETUP"); + + return; //should exit instead and print the error + } + + __android_log_print(ANDROID_LOG_INFO,"godot","*****SETUP OK"); + + //video driver is determined here, because once initialized, it cant be changed + String vd = Globals::get_singleton()->get("display/driver"); + + + if (vd.to_upper()=="GLES1") + env->CallVoidMethod(_godot_instance, _on_video_init, (jboolean)false); + else + env->CallVoidMethod(_godot_instance, _on_video_init, (jboolean)true); + + __android_log_print(ANDROID_LOG_INFO,"godot","**START"); + + input_mutex=Mutex::create(); + suspend_mutex=Mutex::create(); + + +} + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_resize(JNIEnv * env, jobject obj, jint width, jint height, jboolean reload) { + + __android_log_print(ANDROID_LOG_INFO,"godot","^_^_^_^_^ resize %lld, %i, %i\n",Thread::get_caller_ID(),width,height); + if (os_android) + os_android->set_display_size(Size2(width,height)); + + /*input_mutex->lock(); + resized=true; + if (reload) + resized_reload=true; + new_size=Size2(width,height); + input_mutex->unlock();*/ + +} + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_newcontext(JNIEnv * env, jobject obj) { + + __android_log_print(ANDROID_LOG_INFO,"godot","^_^_^_^_^ newcontext %lld\n",Thread::get_caller_ID()); + if (os_android && step > 0) { + + os_android->reload_gfx(); + } + +} + + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_quit(JNIEnv * env, jobject obj) { + + input_mutex->lock(); + quit_request=true; + input_mutex->unlock(); + +} + +static void _initialize_java_modules() { + + + String modules = Globals::get_singleton()->get("android/modules"); + Vector<String> mods = modules.split(",",false); + __android_log_print(ANDROID_LOG_INFO,"godot","mod count: %i",mods.size()); + + if (mods.size()) { + + JNIEnv *env = ThreadAndroid::get_env(); + + jclass activityClass = env->FindClass("com/android/godot/Godot"); + + jmethodID getClassLoader = env->GetMethodID(activityClass,"getClassLoader", "()Ljava/lang/ClassLoader;"); + + jobject cls = env->CallObjectMethod(_godot_instance, getClassLoader); + + jclass classLoader = env->FindClass("java/lang/ClassLoader"); + + jmethodID findClass = env->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); + + for (int i=0;i<mods.size();i++) { + + String m = mods[i]; + //jclass singletonClass = env->FindClass(m.utf8().get_data()); + + print_line("LOADING MODULE: "+m); + jstring strClassName = env->NewStringUTF(m.utf8().get_data()); + jclass singletonClass = (jclass)env->CallObjectMethod(cls, findClass, strClassName); + + if (!singletonClass) { + + ERR_EXPLAIN("Couldn't find singleton for class: "+m); + ERR_CONTINUE(!singletonClass); + } + + __android_log_print(ANDROID_LOG_INFO,"godot","****^*^*?^*^*class data %x",singletonClass); + jmethodID initialize = env->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lcom/android/godot/Godot$SingletonBase;"); + + jobject obj = env->CallStaticObjectMethod(singletonClass,initialize,_godot_instance); + __android_log_print(ANDROID_LOG_INFO,"godot","****^*^*?^*^*class instance %x",obj); + jobject gob = env->NewGlobalRef(obj); + + + } + + } + +} + + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_step(JNIEnv * env, jobject obj) +{ + + + ThreadAndroid::setup_thread(); + + //__android_log_print(ANDROID_LOG_INFO,"godot","**STEP EVENT! - %p-%i\n",env,Thread::get_caller_ID()); + + + suspend_mutex->lock(); + input_mutex->lock(); + //first time step happens, initialize + if (step == 0) { + // ugly hack to initialize the rest of the engine + // because of the way android forces you to do everything with threads + + _initialize_java_modules(); + + Main::setup2(); + ++step; + suspend_mutex->unlock(); + input_mutex->unlock(); + return; + }; + if (step == 1) { + if (!Main::start()) { + + input_mutex->unlock(); + suspend_mutex->lock(); + return; //should exit instead and print the error + } + + os_android->main_loop_begin(); + ++step; + } + + while(pointer_events.size()) { + + JAndroidPointerEvent jpe=pointer_events.front()->get(); + os_android->process_touch(jpe.what,jpe.pointer,jpe.points); + + pointer_events.pop_front(); + } + + while (key_events.size()) { + + InputEvent event = key_events.front()->get(); + os_android->process_event(event); + + key_events.pop_front(); + }; + + if (quit_request) { + + os_android->main_loop_request_quit(); + quit_request=false; + } + + + input_mutex->unlock(); + + os_android->process_accelerometer(accelerometer); + + if (os_android->main_loop_iterate()==true) { + + jclass cls = env->FindClass("com/android/godot/Godot"); + jmethodID _finish = env->GetMethodID(cls, "forceQuit", "()V"); + env->CallVoidMethod(_godot_instance, _finish); + __android_log_print(ANDROID_LOG_INFO,"godot","**FINISH REQUEST!!! - %p-%i\n",env,Thread::get_caller_ID()); + + } + + suspend_mutex->unlock(); + +} + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_touch(JNIEnv * env, jobject obj, jint ev,jint pointer, jint count, jintArray positions) { + + + + //__android_log_print(ANDROID_LOG_INFO,"godot","**TOUCH EVENT! - %p-%i\n",env,Thread::get_caller_ID()); + + + Vector<OS_Android::TouchPos> points; + for(int i=0;i<count;i++) { + + jint p[3]; + env->GetIntArrayRegion(positions,i*3,3,p); + OS_Android::TouchPos tp; + tp.pos=Point2(p[1],p[2]); + tp.id=p[0]; + points.push_back(tp); + } + + JAndroidPointerEvent jpe; + jpe.pointer=pointer; + jpe.points=points; + jpe.what=ev; + + input_mutex->lock(); + + pointer_events.push_back(jpe); + + input_mutex->unlock(); + //if (os_android) +// os_android->process_touch(ev,pointer,points); + +} + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_key(JNIEnv * env, jobject obj, jint ev, jint p_unicode_char, jboolean p_pressed) { + + InputEvent ievent; + ievent.type = InputEvent::KEY; + ievent.device = 0; + int val = p_unicode_char; + ievent.key.scancode = val; + ievent.key.unicode = val; + if (val == 61448) { + ievent.key.scancode = KEY_BACKSPACE; + ievent.key.unicode = KEY_BACKSPACE; + }; + if (val == 61453) { + ievent.key.scancode = KEY_ENTER; + ievent.key.unicode = KEY_ENTER; + }; + + input_mutex->lock(); + key_events.push_back(ievent); + input_mutex->unlock(); +}; + + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_accelerometer(JNIEnv * env, jobject obj, jfloat x, jfloat y, jfloat z) { + + input_mutex->lock(); + accelerometer=Vector3(x,y,z); + input_mutex->unlock(); + +} + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_focusin(JNIEnv * env, jobject obj){ + + if (!suspend_mutex) + return; + suspend_mutex->lock(); + + if (os_android && step > 0) + os_android->main_loop_focusin(); + + suspend_mutex->unlock(); +} + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_focusout(JNIEnv * env, jobject obj){ + + if (!suspend_mutex) + return; + suspend_mutex->lock(); + + if (os_android && step > 0) + os_android->main_loop_focusout(); + + suspend_mutex->unlock(); + +} + + + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_audio(JNIEnv * env, jobject obj) { + + ThreadAndroid::setup_thread(); + AudioDriverAndroid::thread_func(env); + + +} + + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_singleton(JNIEnv * env, jobject obj, jstring name,jobject p_object){ + + String singname = env->GetStringUTFChars( name, NULL ); + JNISingleton *s = memnew( JNISingleton ); + s->set_instance(env->NewGlobalRef(p_object)); + jni_singletons[singname]=s; + + Globals::get_singleton()->add_singleton(Globals::Singleton(singname,s)); + Globals::get_singleton()->set(singname,s); + +} + + +static Variant::Type get_jni_type(const String& p_type) { + + static struct { + const char *name; + Variant::Type type; + } _type_to_vtype[]={ + {"void",Variant::NIL}, + {"boolean",Variant::BOOL}, + {"int",Variant::INT}, + {"float",Variant::REAL}, + {"double", Variant::REAL}, + {"java.lang.String",Variant::STRING}, + {"[I",Variant::INT_ARRAY}, + {"[F",Variant::REAL_ARRAY}, + {"[java.lang.String",Variant::STRING_ARRAY}, + {"com.android.godot.Dictionary", Variant::DICTIONARY}, + {NULL,Variant::NIL} + }; + + int idx=0; + + while (_type_to_vtype[idx].name) { + + if (p_type==_type_to_vtype[idx].name) + return _type_to_vtype[idx].type; + + idx++; + } + + return Variant::NIL; +} + + +static const char* get_jni_sig(const String& p_type) { + + print_line("getting sig for " + p_type); + static struct { + const char *name; + const char *sig; + } _type_to_vtype[]={ + {"void","V"}, + {"boolean","Z"}, + {"int","I"}, + {"float","F"}, + {"double","D"}, + {"java.lang.String","Ljava/lang/String;"}, + {"com.android.godot.Dictionary", "Lcom/android/godot/Dictionary;"}, + {"[I","[I"}, + {"[F","[F"}, + {"[java.lang.String","[Ljava/lang/String;"}, + {NULL,"V"} + }; + + int idx=0; + + while (_type_to_vtype[idx].name) { + + if (p_type==_type_to_vtype[idx].name) + return _type_to_vtype[idx].sig; + + idx++; + } + + + return "Ljava/lang/Object;"; +} + +JNIEXPORT jstring JNICALL Java_com_android_godot_GodotLib_getGlobal(JNIEnv * env, jobject obj, jstring path) { + + String js = env->GetStringUTFChars( path, NULL ); + + return env->NewStringUTF(Globals::get_singleton()->get(js).operator String().utf8().get_data()); + + +} + + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_method(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args){ + + String singname = env->GetStringUTFChars( sname, NULL ); + + ERR_FAIL_COND(!jni_singletons.has(singname)); + + JNISingleton *s = jni_singletons.get(singname); + + + String mname = env->GetStringUTFChars( name, NULL ); + String retval = env->GetStringUTFChars( ret, NULL ); + Vector<Variant::Type> types; + String cs="("; + + + int stringCount = env->GetArrayLength(args); + + print_line("Singl: "+singname+" Method: "+mname+" RetVal: "+retval); + for (int i=0; i<stringCount; i++) { + + jstring string = (jstring) env->GetObjectArrayElement(args, i); + const char *rawString = env->GetStringUTFChars(string, 0); + types.push_back(get_jni_type(String(rawString))); + cs+=get_jni_sig(String(rawString)); + } + + cs+=")"; + cs+=get_jni_sig(retval); + jclass cls = env->GetObjectClass(s->get_instance()); + print_line("METHOD: "+mname+" sig: "+cs); + jmethodID mid = env->GetMethodID(cls, mname.ascii().get_data(), cs.ascii().get_data()); + if (!mid) { + + print_line("FAILED GETTING METHOID "+mname); + } + + s->add_method(mname,mid,types,get_jni_type(retval)); + + +} + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_callobject(JNIEnv * env, jobject p_obj, jint ID, jstring method, jobjectArray params) { + + String str_method = env->GetStringUTFChars( method, NULL ); + + Object* obj = ObjectDB::get_instance(ID); + ERR_FAIL_COND(!obj); + + int count = env->GetArrayLength(params); + Variant* vlist = (Variant*)alloca(sizeof(Variant) * count); + Variant** vptr = (Variant**)alloca(sizeof(Variant*) * count); + for (int i=0; i<count; i++) { + + jobject obj = env->GetObjectArrayElement(params, i); + Variant v = _jobject_to_variant(env, obj); + memnew_placement(&vlist[i], Variant); + vlist[i] = v; + vptr[i] = &vlist[i]; + }; + + Variant::CallError err; + obj->call(str_method, (const Variant**)vptr, count, err); + // something +}; + + +//Main::cleanup(); + +//return os.get_exit_code(); +#endif diff --git a/platform/android/java_glue.h b/platform/android/java_glue.h new file mode 100644 index 000000000..7a0666f63 --- /dev/null +++ b/platform/android/java_glue.h @@ -0,0 +1,58 @@ +/*************************************************************************/ +/* java_glue.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef ANDROID_NATIVE_ACTIVITY + +#ifndef JAVA_GLUE_H +#define JAVA_GLUE_H + +#include <jni.h> +#include <android/log.h> + + +extern "C" { + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_resize(JNIEnv * env, jobject obj, jint width, jint height, jboolean reload); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_newcontext(JNIEnv * env, jobject obj); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_step(JNIEnv * env, jobject obj); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_quit(JNIEnv * env, jobject obj); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_touch(JNIEnv * env, jobject obj, jint ev,jint pointer, jint count, jintArray positions); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_key(JNIEnv * env, jobject obj, jint ev, jint p_unicode_char, jboolean p_pressed); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_audio(JNIEnv * env, jobject obj); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_accelerometer(JNIEnv * env, jobject obj, jfloat x, jfloat y, jfloat z); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_focusin(JNIEnv * env, jobject obj); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_focusout(JNIEnv * env, jobject obj); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_singleton(JNIEnv * env, jobject obj, jstring name,jobject p_object); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_method(JNIEnv * env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args); + JNIEXPORT jstring JNICALL Java_com_android_godot_GodotLib_getGlobal(JNIEnv * env, jobject obj, jstring path); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_callobject(JNIEnv * env, jobject obj, jint ID, jstring method, jobjectArray params); +}; + + +#endif +#endif // JAVA_GLUE_H |
