diff options
Diffstat (limited to 'platform')
-rw-r--r-- | platform/android/export/export.cpp | 39 | ||||
-rw-r--r-- | platform/android/globals/global_defaults.cpp | 1 | ||||
-rw-r--r-- | platform/android/java/src/com/android/godot/Godot.java | 233 | ||||
-rw-r--r-- | platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java | 27 | ||||
-rw-r--r-- | platform/android/java/src/com/android/godot/GodotDownloaderService.java | 47 | ||||
-rw-r--r-- | platform/android/java/src/com/android/godot/GodotLib.java | 2 | ||||
-rw-r--r-- | platform/android/java/src/com/android/godot/GodotView.java | 236 | ||||
-rw-r--r-- | platform/android/java_glue.cpp | 91 | ||||
-rw-r--r-- | platform/android/java_glue.h | 2 | ||||
-rw-r--r-- | platform/android/os_android.cpp | 21 | ||||
-rw-r--r-- | platform/android/os_android.h | 3 | ||||
-rw-r--r-- | platform/iphone/app_delegate.mm | 41 | ||||
-rw-r--r-- | platform/osx/os_osx.h | 4 | ||||
-rw-r--r-- | platform/osx/os_osx.mm | 35 |
14 files changed, 694 insertions, 88 deletions
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index d1ee7087e7..f47ff4ed50 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -258,7 +258,11 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant& String n=p_name; - if (n=="version/code") + if (n=="custom_package/debug") + custom_debug_package=p_value; + else if (n=="custom_package/release") + custom_release_package=p_value; + else if (n=="version/code") version_code=p_value; else if (n=="version/name") version_name=p_value; @@ -317,8 +321,11 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant& bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret) const{ String n=p_name; - - if (n=="version/code") + if (n=="custom_package/debug") + r_ret=custom_debug_package; + else if (n=="custom_package/release") + r_ret=custom_release_package; + else if (n=="version/code") r_ret=version_code; else if (n=="version/name") r_ret=version_name; @@ -389,7 +396,7 @@ void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release_user" ) ); p_list->push_back( PropertyInfo( Variant::BOOL, "apk_expansion/enable" ) ); p_list->push_back( PropertyInfo( Variant::STRING, "apk_expansion/SALT" ) ); - p_list->push_back( PropertyInfo( Variant::STRING, "apk_expansion/pubic_key" ) ); + p_list->push_back( PropertyInfo( Variant::STRING, "apk_expansion/public_key",PROPERTY_HINT_MULTILINE_TEXT ) ); const char **perms = android_perms; while(*perms) { @@ -1095,6 +1102,12 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d ep.step("Adding Files..",1); Error err=OK; Vector<String> cl = cmdline.strip_edges().split(" "); + for(int i=0;i<cl.size();i++) { + if (cl[i].strip_edges().length()==0) { + cl.remove(i); + i--; + } + } if (p_dumb) { @@ -1123,12 +1136,12 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d } err = save_pack(pf); memdelete(pf); - cl.push_back("-main_pack"); - cl.push_back(apkfname); - cl.push_back("-main_pack_md5"); + + cl.push_back("-use_apk_expansion"); + cl.push_back("-apk_expansion_md5"); cl.push_back(FileAccess::get_md5(fullpath)); - cl.push_back("-main_pack_cfg"); - cl.push_back(apk_expansion_salt+","+apk_expansion_pkey); + cl.push_back("-apk_expansion_key"); + cl.push_back(apk_expansion_pkey.strip_edges()); } else { @@ -1562,10 +1575,10 @@ bool EditorExportPlatformAndroid::can_export(String *r_error) const { if (apk_expansion) { - if (apk_expansion_salt=="") { - valid=false; - err+="Invalid SALT for apk expansion.\n"; - } + //if (apk_expansion_salt=="") { + // valid=false; + // err+="Invalid SALT for apk expansion.\n"; + //} if (apk_expansion_pkey=="") { valid=false; err+="Invalid public key for apk expansion.\n"; diff --git a/platform/android/globals/global_defaults.cpp b/platform/android/globals/global_defaults.cpp index 9bde79e63c..84a586d22d 100644 --- a/platform/android/globals/global_defaults.cpp +++ b/platform/android/globals/global_defaults.cpp @@ -6,6 +6,7 @@ void register_android_global_defaults() { GLOBAL_DEF("rasterizer.Android/use_fragment_lighting",false); + GLOBAL_DEF("rasterizer.Android/fp16_framebuffer",false); GLOBAL_DEF("display.Android/driver","GLES2"); // GLOBAL_DEF("rasterizer.Android/trilinear_mipmap_filter",false); diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java index 9cadeb4231..11fb894545 100644 --- a/platform/android/java/src/com/android/godot/Godot.java +++ b/platform/android/java/src/com/android/godot/Godot.java @@ -63,6 +63,10 @@ import com.android.godot.input.*; import java.io.InputStream; import javax.microedition.khronos.opengles.GL10; +import java.security.MessageDigest; +import java.io.File; +import java.io.FileInputStream; +import java.util.LinkedList; public class Godot extends Activity implements SensorEventListener { @@ -138,7 +142,11 @@ public class Godot extends Activity implements SensorEventListener */ + private String[] command_line; + public GodotView mView; + private boolean godot_initialized=false; + private SensorManager mSensorManager; private Sensor mAccelerometer; @@ -190,9 +198,9 @@ public class Godot extends Activity implements SensorEventListener // GodotEditText layout GodotEditText edittext = new GodotEditText(this); - edittext.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT)); + edittext.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT)); // ...add to FrameLayout - layout.addView(edittext); + layout.addView(edittext); mView = new GodotView(getApplication(),io,use_gl2, this); layout.addView(mView,new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT)); @@ -216,71 +224,206 @@ public class Godot extends Activity implements SensorEventListener private String[] getCommandLine() { - - InputStream is; - try { - is = getAssets().open("/_cl_"); - byte[] len = new byte[4]; - int r = is.read(len); - if (r<4) { - System.out.printf("**ERROR** Wrong cmdline length.\n"); - return new String[0]; - } - int argc=((int)(len[3])<<24) | ((int)(len[2])<<16) | ((int)(len[1])<<8) | ((int)(len[0])); - String[] cmdline = new String[argc]; - for(int i=0;i<argc;i++) { - r = is.read(len); - if (r<4) { - System.out.printf("**ERROR** Wrong cmdline param lenght.\n"); - return new String[0]; - } - int strlen=((int)(len[3])<<24) | ((int)(len[2])<<16) | ((int)(len[1])<<8) | ((int)(len[0])); - if (strlen>65535) { - System.out.printf("**ERROR** Wrong command len\n"); - return new String[0]; - } - byte[] arg = new byte[strlen]; - r = is.read(arg); - if (r!=strlen) { - cmdline[i]=new String(arg,"UTF-8"); - } - + InputStream is; + try { + is = getAssets().open("_cl_"); + byte[] len = new byte[4]; + int r = is.read(len); + if (r<4) { + System.out.printf("**ERROR** Wrong cmdline length.\n"); + Log.d("GODOT", "**ERROR** Wrong cmdline length.\n"); + return new String[0]; + } + int argc=((int)(len[3]&0xFF)<<24) | ((int)(len[2]&0xFF)<<16) | ((int)(len[1]&0xFF)<<8) | ((int)(len[0]&0xFF)); + String[] cmdline = new String[argc]; + + for(int i=0;i<argc;i++) { + r = is.read(len); + if (r<4) { + + Log.d("GODOT", "**ERROR** Wrong cmdline param lenght.\n"); + return new String[0]; + } + int strlen=((int)(len[3]&0xFF)<<24) | ((int)(len[2]&0xFF)<<16) | ((int)(len[1]&0xFF)<<8) | ((int)(len[0]&0xFF)); + if (strlen>65535) { + Log.d("GODOT", "**ERROR** Wrong command len\n"); + return new String[0]; + } + byte[] arg = new byte[strlen]; + r = is.read(arg); + if (r==strlen) { + cmdline[i]=new String(arg,"UTF-8"); + } } - return cmdline; } catch (Exception e) { - + e.printStackTrace(); + System.out.printf("**ERROR** No commandline.\n"); + Log.d("GODOT", "**ERROR** Exception " + e.getClass().getName() + ":" + e.getMessage()); return new String[0]; } } - @Override protected void onCreate(Bundle icicle) { - System.out.printf("** GODOT ACTIVITY CREATED HERE ***\n"); + String expansion_pack_path; - super.onCreate(icicle); - _self = this; - Window window = getWindow(); - window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON - | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + private void initializeGodot() { + if (expansion_pack_path!=null) { + String[] new_cmdline; + int cll=0; + if (command_line!=null) { + new_cmdline = new String[ command_line.length + 2 ]; + cll=command_line.length; + for(int i=0;i<command_line.length;i++) { + new_cmdline[i]=command_line[i]; + } + } else { + new_cmdline = new String[ 2 ]; + } + + new_cmdline[cll]="-main_pack"; + new_cmdline[cll+1]=expansion_pack_path; + command_line=new_cmdline; + } io = new GodotIO(this); io.unique_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID); GodotLib.io=io; - GodotLib.initialize(this,io.needsReloadHooks(),getCommandLine()); + GodotLib.initialize(this,io.needsReloadHooks(),command_line); mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); result_callback = null; - + mPaymentsManager = PaymentsManager.createManager(this).initService(); + godot_initialized=true; + + } + + + @Override protected void onCreate(Bundle icicle) { + + System.out.printf("** GODOT ACTIVITY CREATED HERE ***\n"); + + super.onCreate(icicle); + _self = this; + Window window = getWindow(); + window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON + | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + //check for apk expansion API + if (true) { + command_line = getCommandLine(); + boolean use_apk_expansion=false; + String main_pack_md5=null; + String main_pack_key=null; + + List<String> new_args = new LinkedList<String>(); + + + for(int i=0;i<command_line.length;i++) { + + boolean has_extra = i< command_line.length -1; + if (command_line[i].equals("-use_apk_expansion")) { + use_apk_expansion=true; + } else if (has_extra && command_line[i].equals("-apk_expansion_md5")) { + main_pack_md5=command_line[i+1]; + i++; + } else if (has_extra && command_line[i].equals("-apk_expansion_key")) { + main_pack_key=command_line[i+1]; + i++; + } else if (command_line[i].trim().length()!=0){ + new_args.add(command_line[i]); + } + } + + if (new_args.isEmpty()) + command_line=null; + else + command_line = new_args.toArray(new String[new_args.size()]); + + if (use_apk_expansion && main_pack_md5!=null && main_pack_key!=null) { + //check that environment is ok! + if (!Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED )) { + Log.d("GODOT", "**ERROR! No media mounted!"); + //show popup and die + } + + // Build the full path to the app's expansion files + try { + expansion_pack_path = Environment.getExternalStorageDirectory().toString() + "/Android/obb/"+this.getPackageName(); + expansion_pack_path+="/"+"main."+getPackageManager().getPackageInfo(getPackageName(), 0).versionCode+"."+this.getPackageName()+".obb"; + } catch (Exception e) { + e.printStackTrace(); + } + + File f = new File(expansion_pack_path); + + boolean pack_valid = true; + Log.d("GODOT","**PACK** - Path "+expansion_pack_path); + + if (!f.exists()) { + + pack_valid=false; + Log.d("GODOT","**PACK** - File does not exist"); + + } else { + try { + + InputStream fis = new FileInputStream(expansion_pack_path); + + // Create MD5 Hash + byte[] buffer = new byte[16384]; + + MessageDigest complete = MessageDigest.getInstance("MD5"); + int numRead; + do { + numRead = fis.read(buffer); + if (numRead > 0) { + complete.update(buffer, 0, numRead); + } + } while (numRead != -1); + + + fis.close(); + byte[] messageDigest = complete.digest(); + + // Create Hex String + StringBuffer hexString = new StringBuffer(); + for (int i=0; i<messageDigest.length; i++) + hexString.append(Integer.toHexString(0xFF & messageDigest[i])); + String md5str = hexString.toString(); + + Log.d("GODOT","**PACK** - My MD5: "+hexString+" - APK md5: "+main_pack_md5); + if (!hexString.equals(main_pack_md5)) { + pack_valid=false; + } + } catch (Exception e) { + e.printStackTrace(); + Log.d("GODOT","**PACK FAIL**"); + pack_valid=false; + } + + + } + + if (!pack_valid) { + + + + } + + } + } + + initializeGodot(); // instanceSingleton( new GodotFacebook(this) ); @@ -299,6 +442,8 @@ public class Godot extends Activity implements SensorEventListener @Override protected void onPause() { super.onPause(); + if (!godot_initialized) + return; mView.onPause(); mSensorManager.unregisterListener(this); GodotLib.focusout(); @@ -310,6 +455,9 @@ public class Godot extends Activity implements SensorEventListener @Override protected void onResume() { super.onResume(); + if (!godot_initialized) + return; + mView.onResume(); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); GodotLib.focusin(); @@ -350,6 +498,7 @@ public class Godot extends Activity implements SensorEventListener @Override public void onBackPressed() { + System.out.printf("** BACK REQUEST!\n"); GodotLib.quit(); } diff --git a/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java b/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java new file mode 100644 index 0000000000..d945a8b192 --- /dev/null +++ b/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java @@ -0,0 +1,27 @@ +package com.android.godot; + +import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager.NameNotFoundException; + +/** + * You should start your derived downloader class when this receiver gets the message + * from the alarm service using the provided service helper function within the + * DownloaderClientMarshaller. This class must be then registered in your AndroidManifest.xml + * file with a section like this: + * <receiver android:name=".GodotDownloaderAlarmReceiver"/> + */ +public class GodotDownloaderAlarmReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + try { + DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent, GodotDownloaderService.class); + } catch (NameNotFoundException e) { + e.printStackTrace(); + } + } +} diff --git a/platform/android/java/src/com/android/godot/GodotDownloaderService.java b/platform/android/java/src/com/android/godot/GodotDownloaderService.java new file mode 100644 index 0000000000..e0fe95ad96 --- /dev/null +++ b/platform/android/java/src/com/android/godot/GodotDownloaderService.java @@ -0,0 +1,47 @@ +package com.android.godot; + +import com.google.android.vending.expansion.downloader.impl.DownloaderService; + +/** + * This class demonstrates the minimal client implementation of the + * DownloaderService from the Downloader library. + */ +public class GodotDownloaderService extends DownloaderService { + // stuff for LVL -- MODIFY FOR YOUR APPLICATION! + private static final String BASE64_PUBLIC_KEY = "REPLACE THIS WITH YOUR PUBLIC KEY"; + // used by the preference obfuscater + private static final byte[] SALT = new byte[] { + 1, 43, -12, -1, 54, 98, + -100, -12, 43, 2, -8, -4, 9, 5, -106, -108, -33, 45, -1, 84 + }; + + /** + * This public key comes from your Android Market publisher account, and it + * used by the LVL to validate responses from Market on your behalf. + */ + @Override + public String getPublicKey() { + return BASE64_PUBLIC_KEY; + } + + /** + * This is used by the preference obfuscater to make sure that your + * obfuscated preferences are different than the ones used by other + * applications. + */ + @Override + public byte[] getSALT() { + return SALT; + } + + /** + * Fill this in with the class name for your alarm receiver. We do this + * because receivers must be unique across all of Android (it's a good idea + * to make sure that your receiver is in your unique package) + */ + @Override + public String getAlarmReceiverClassName() { + return GodotDownloaderAlarmReceiver.class.getName(); + } + +} diff --git a/platform/android/java/src/com/android/godot/GodotLib.java b/platform/android/java/src/com/android/godot/GodotLib.java index ad803f8e8d..6e2462b4f1 100644 --- a/platform/android/java/src/com/android/godot/GodotLib.java +++ b/platform/android/java/src/com/android/godot/GodotLib.java @@ -52,6 +52,8 @@ public class GodotLib { 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_scancode, int p_unicode_char, boolean p_pressed); + public static native void joybutton(int p_device, int p_but, boolean p_pressed); + public static native void joyaxis(int p_device, int p_axis, float p_value); public static native void focusin(); public static native void focusout(); public static native void audio(); diff --git a/platform/android/java/src/com/android/godot/GodotView.java b/platform/android/java/src/com/android/godot/GodotView.java index f02cc00c28..f62431b94b 100644 --- a/platform/android/java/src/com/android/godot/GodotView.java +++ b/platform/android/java/src/com/android/godot/GodotView.java @@ -35,6 +35,7 @@ import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.content.ContextWrapper; +import android.view.InputDevice; import java.io.File; import javax.microedition.khronos.egl.EGL10; @@ -99,22 +100,251 @@ public class GodotView extends GLSurfaceView { return activity.gotTouchEvent(event); }; + public int get_godot_button(int keyCode) { + + int button = 0; + switch (keyCode) { + case KeyEvent.KEYCODE_BUTTON_A: // Android A is SNES B + button = 0; + break; + case KeyEvent.KEYCODE_BUTTON_B: + button = 1; + break; + case KeyEvent.KEYCODE_BUTTON_X: // Android X is SNES Y + button = 2; + break; + case KeyEvent.KEYCODE_BUTTON_Y: + button = 3; + break; + case KeyEvent.KEYCODE_BUTTON_L1: + button = 4; + break; + case KeyEvent.KEYCODE_BUTTON_L2: + button = 6; + break; + case KeyEvent.KEYCODE_BUTTON_R1: + button = 5; + break; + case KeyEvent.KEYCODE_BUTTON_R2: + button = 7; + break; + case KeyEvent.KEYCODE_BUTTON_SELECT: + button = 10; + break; + case KeyEvent.KEYCODE_BUTTON_START: + button = 11; + break; + case KeyEvent.KEYCODE_BUTTON_THUMBL: + button = 8; + break; + case KeyEvent.KEYCODE_BUTTON_THUMBR: + button = 9; + break; + case KeyEvent.KEYCODE_DPAD_UP: + button = 12; + break; + case KeyEvent.KEYCODE_DPAD_DOWN: + button = 13; + break; + case KeyEvent.KEYCODE_DPAD_LEFT: + button = 14; + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + button = 15; + break; + + default: + button = keyCode - KeyEvent.KEYCODE_BUTTON_1; + break; + }; + + return button; + }; + @Override public boolean onKeyUp(int keyCode, KeyEvent event) { - GodotLib.key(keyCode, event.getUnicodeChar(0), false); + + if (keyCode == KeyEvent.KEYCODE_BACK) { + return true; + } + + if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { + return super.onKeyUp(keyCode, event); + }; + + int source = event.getSource(); + if ((source & InputDevice.SOURCE_JOYSTICK) != 0 || (source & InputDevice.SOURCE_DPAD) != 0 || (source & InputDevice.SOURCE_GAMEPAD) != 0) { + + int button = get_godot_button(keyCode); + int device = event.getDeviceId(); + + GodotLib.joybutton(device, button, false); + return true; + } else { + + GodotLib.key(keyCode, event.getUnicodeChar(0), false); + }; return super.onKeyUp(keyCode, event); }; @Override public boolean onKeyDown(int keyCode, KeyEvent event) { - GodotLib.key(keyCode, event.getUnicodeChar(0), true); + if (keyCode == KeyEvent.KEYCODE_BACK) { + GodotLib.quit(); // press 'back' button should not terminate program // normal handle 'back' event in game logic return true; } + + if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { + return super.onKeyDown(keyCode, event); + }; + + int source = event.getSource(); + //Log.e(TAG, String.format("Key down! source %d, device %d, joystick %d, %d, %d", event.getDeviceId(), source, (source & InputDevice.SOURCE_JOYSTICK), (source & InputDevice.SOURCE_DPAD), (source & InputDevice.SOURCE_GAMEPAD))); + + if ((source & InputDevice.SOURCE_JOYSTICK) != 0 || (source & InputDevice.SOURCE_DPAD) != 0 || (source & InputDevice.SOURCE_GAMEPAD) != 0) { + + if (event.getRepeatCount() > 0) // ignore key echo + return true; + int button = get_godot_button(keyCode); + int device = event.getDeviceId(); + //Log.e(TAG, String.format("joy button down! button %x, %d, device %d", keyCode, button, device)); + + GodotLib.joybutton(device, button, true); + return true; + + } else { + GodotLib.key(keyCode, event.getUnicodeChar(0), true); + }; return super.onKeyDown(keyCode, event); } - private void init(boolean translucent, int depth, int stencil) { + public float axis_value(MotionEvent p_event, InputDevice p_device, int p_axis, int p_pos) { + + final InputDevice.MotionRange range = p_device.getMotionRange(p_axis, p_event.getSource()); + if (range == null) + return 0; + + //Log.e(TAG, String.format("axis ranges %f, %f, %f", range.getRange(), range.getMin(), range.getMax())); + + final float flat = range.getFlat(); + final float value = + p_pos < 0 ? p_event.getAxisValue(p_axis): + p_event.getHistoricalAxisValue(p_axis, p_pos); + + final float absval = Math.abs(value); + if (absval <= flat) { + return 0; + }; + + final float ret = (value - range.getMin()) / range.getRange() * 2 - 1.0f; + + return ret; + }; + + float[] last_axis_values = { 0, 0, 0, 0, -1, -1 }; + boolean[] last_axis_buttons = { false, false, false, false, false, false }; // dpad up down left right, ltrigger, rtrigger + + public void process_axis_state(MotionEvent p_event, int p_pos) { + + int device_id = p_event.getDeviceId(); + InputDevice device = p_event.getDevice(); + float val; + + val = axis_value(p_event, device, MotionEvent.AXIS_X, p_pos); + if (val != last_axis_values[0]) { + last_axis_values[0] = val; + //Log.e(TAG, String.format("axis moved! axis %d, value %f", 0, val)); + GodotLib.joyaxis(device_id, 0, val); + }; + + val = axis_value(p_event, device, MotionEvent.AXIS_Y, p_pos); + if (val != last_axis_values[1]) { + last_axis_values[1] = val; + //Log.e(TAG, String.format("axis moved! axis %d, value %f", 1, val)); + GodotLib.joyaxis(device_id, 1, val); + }; + + val = axis_value(p_event, device, MotionEvent.AXIS_Z, p_pos); + if (val != last_axis_values[2]) { + last_axis_values[2] = val; + //Log.e(TAG, String.format("axis moved! axis %d, value %f", 2, val)); + GodotLib.joyaxis(device_id, 2, val); + }; + + val = axis_value(p_event, device, MotionEvent.AXIS_RZ, p_pos); + if (val != last_axis_values[3]) { + last_axis_values[3] = val; + //Log.e(TAG, String.format("axis moved! axis %d, value %f", 3, val)); + GodotLib.joyaxis(device_id, 3, val); + }; + + val = axis_value(p_event, device, MotionEvent.AXIS_LTRIGGER, p_pos); + if (val != last_axis_values[4]) { + last_axis_values[4] = val; + if ((val != 0) != (last_axis_buttons[4])) { + last_axis_buttons[4] = (val != 0); + GodotLib.joybutton(device_id, 6, (val != 0)); + }; + }; + + val = axis_value(p_event, device, MotionEvent.AXIS_RTRIGGER, p_pos); + if (val != last_axis_values[5]) { + last_axis_values[5] = val; + if ((val != 0) != (last_axis_buttons[5])) { + last_axis_buttons[5] = (val != 0); + GodotLib.joybutton(device_id, 7, (val != 0)); + }; + }; + + val = axis_value(p_event, device, MotionEvent.AXIS_HAT_Y, p_pos); + + if (last_axis_buttons[0] != (val > 0)) { + last_axis_buttons[0] = val > 0; + GodotLib.joybutton(device_id, 12, val > 0); + }; + if (last_axis_buttons[1] != (val < 0)) { + last_axis_buttons[1] = val < 0; + GodotLib.joybutton(device_id, 13, val > 0); + }; + + val = axis_value(p_event, device, MotionEvent.AXIS_HAT_X, p_pos); + if (last_axis_buttons[2] != (val < 0)) { + last_axis_buttons[2] = val < 0; + GodotLib.joybutton(device_id, 14, val < 0); + }; + if (last_axis_buttons[3] != (val > 0)) { + last_axis_buttons[3] = val > 0; + GodotLib.joybutton(device_id, 15, val > 0); + }; + }; + + @Override public boolean onGenericMotionEvent(MotionEvent event) { + + if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) { + + // Process all historical movement samples in the batch + final int historySize = event.getHistorySize(); + + // Process the movements starting from the + // earliest historical position in the batch + for (int i = 0; i < historySize; i++) { + // Process the event at historical position i + process_axis_state(event, i); + } + + // Process the current movement sample in the batch (position -1) + process_axis_state(event, -1); + return true; + + + }; + + return super.onGenericMotionEvent(event); + }; + + + private void init(boolean translucent, int depth, int stencil) { this.setFocusableInTouchMode(true); /* By default, GLSurfaceView() creates a RGB_565 opaque surface. diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp index b11994eef0..5c39cdbacc 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -581,6 +581,8 @@ static Vector3 accelerometer; static HashMap<String,JNISingleton*> jni_singletons; static jobject godot_io; +static Vector<int> joy_device_ids; + typedef void (*GFXInitFunc)(void *ud,bool gl2); static jmethodID _on_video_init=0; @@ -747,8 +749,34 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, } + const char ** cmdline=NULL; + int cmdlen=0; + bool use_apk_expansion=false; + if (p_cmdline) { + int cmdlen = env->GetArrayLength(p_cmdline); + if (cmdlen) { + cmdline = (const char**)malloc((env->GetArrayLength(p_cmdline)+1)*sizeof(const char*)); + cmdline[cmdlen]=NULL; + + for (int i=0; i<cmdlen; i++) { + + jstring string = (jstring) env->GetObjectArrayElement(p_cmdline, i); + const char *rawString = env->GetStringUTFChars(string, 0); + if (!rawString) { + __android_log_print(ANDROID_LOG_INFO,"godot","cmdline arg %i is null\n",i); + } else { + // __android_log_print(ANDROID_LOG_INFO,"godot","cmdline arg %i is: %s\n",i,rawString); + + if (strcmp(rawString,"-main_pack")==0) + use_apk_expansion=true; + } + + cmdline[i]=rawString; + } + } + } - 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, _play_video, _is_video_playing, _pause_video, _stop_video); + 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, _play_video, _is_video_playing, _pause_video, _stop_video,use_apk_expansion); os_android->set_need_reload_hooks(p_need_reload_hook); char wd[500]; @@ -759,16 +787,6 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, __android_log_print(ANDROID_LOG_INFO,"godot","**SETUP"); - const char ** cmdline=NULL; - int cmdlen = env->GetArrayLength(p_cmdline); - cmdline = (const char**)malloc((env->GetArrayLength(p_cmdline)+1)*sizeof(const char*)); - cmdline[cmdlen]=NULL; - for (int i=0; i<cmdlen; i++) { - - jstring string = (jstring) env->GetObjectArrayElement(p_cmdline, i); - const char *rawString = env->GetStringUTFChars(string, 0); - cmdline[i]=rawString; - } #if 0 char *args[]={"-test","render",NULL}; @@ -833,6 +851,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_quit(JNIEnv * env, jobjec input_mutex->lock(); quit_request=true; + print_line("BACK PRESSED"); input_mutex->unlock(); } @@ -1262,6 +1281,49 @@ static unsigned int android_get_keysym(unsigned int p_code) { return KEY_UNKNOWN; } +static int find_device(int p_device) { + + for (int i=0; i<joy_device_ids.size(); i++) { + + if (joy_device_ids[i] == p_device) { + //print_line("found device at "+String::num(i)); + return i; + }; + }; + + //print_line("adding a device at" + String::num(joy_device_ids.size())); + joy_device_ids.push_back(p_device); + + return joy_device_ids.size() - 1; +}; + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_joybutton(JNIEnv * env, jobject obj, jint p_device, jint p_button, jboolean p_pressed) { + + InputEvent ievent; + ievent.type = InputEvent::JOYSTICK_BUTTON; + ievent.device = find_device(p_device); + ievent.joy_button.button_index = p_button; + ievent.joy_button.pressed = p_pressed; + + input_mutex->lock(); + key_events.push_back(ievent); + input_mutex->unlock(); +}; + +JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_joyaxis(JNIEnv * env, jobject obj, jint p_device, jint p_axis, jfloat p_value) { + + InputEvent ievent; + ievent.type = InputEvent::JOYSTICK_MOTION; + ievent.device = find_device(p_device); + ievent.joy_motion.axis = p_axis; + ievent.joy_motion.axis_value = p_value; + + input_mutex->lock(); + key_events.push_back(ievent); + input_mutex->unlock(); +}; + + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_key(JNIEnv * env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed) { InputEvent ievent; @@ -1289,7 +1351,10 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_key(JNIEnv * env, jobject } else if (val == 61453) { ievent.key.scancode = KEY_ENTER; ievent.key.unicode = KEY_ENTER; - } + } else if (p_scancode==4) { + + quit_request=true; + } input_mutex->lock(); key_events.push_back(ievent); @@ -1390,7 +1455,7 @@ static Variant::Type get_jni_type(const String& p_type) { 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; diff --git a/platform/android/java_glue.h b/platform/android/java_glue.h index 6dc89418b5..379718a23e 100644 --- a/platform/android/java_glue.h +++ b/platform/android/java_glue.h @@ -43,6 +43,8 @@ extern "C" { 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 p_scancode, jint p_unicode_char, jboolean p_pressed); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_joybutton(JNIEnv * env, jobject obj, jint p_device, jint p_button, jboolean p_pressed); + JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_joyaxis(JNIEnv * env, jobject obj, jint p_device, jint p_axis, jfloat p_value); 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); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 5bc433e85f..5fad4386fa 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -87,11 +87,17 @@ void OS_Android::initialize_core() { #else - FileAccess::make_default<FileAccessBufferedFA<FileAccessJAndroid> >(FileAccess::ACCESS_RESOURCES); + if (use_apk_expansion) + FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES); + else + FileAccess::make_default<FileAccessBufferedFA<FileAccessJAndroid> >(FileAccess::ACCESS_RESOURCES); FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA); FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM); //FileAccessBufferedFA<FileAccessUnix>::make_default(); - DirAccess::make_default<DirAccessJAndroid>(DirAccess::ACCESS_RESOURCES); + if (use_apk_expansion) + DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_RESOURCES); + else + DirAccess::make_default<DirAccessJAndroid>(DirAccess::ACCESS_RESOURCES); DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA); DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM); @@ -698,9 +704,10 @@ void OS_Android::native_video_stop() { video_stop_func(); } -OS_Android::OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func) { +OS_Android::OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func,bool p_use_apk_expansion) { + use_apk_expansion=p_use_apk_expansion; default_videomode.width=800; default_videomode.height=600; default_videomode.fullscreen=true; @@ -720,10 +727,10 @@ OS_Android::OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFu get_model_func=p_get_model_func; get_unique_id_func=p_get_unique_id; - video_play_func = p_video_play_func; - video_is_playing_func = p_video_is_playing_func; - video_pause_func = p_video_pause_func; - video_stop_func = p_video_stop_func; + video_play_func = p_video_play_func; + video_is_playing_func = p_video_is_playing_func; + video_pause_func = p_video_pause_func; + video_stop_func = p_video_stop_func; show_virtual_keyboard_func = p_show_vk; hide_virtual_keyboard_func = p_hide_vk; diff --git a/platform/android/os_android.h b/platform/android/os_android.h index e6d0f7eded..bc52a43002 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -88,6 +88,7 @@ private: bool use_gl2; bool use_reload_hooks; + bool use_apk_expansion; Rasterizer *rasterizer; VisualServer *visual_server; @@ -213,7 +214,7 @@ public: virtual void native_video_pause(); virtual void native_video_stop(); - OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func); + OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func,bool p_use_apk_expansion); ~OS_Android(); }; diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm index c5ac5d9263..9ba95ff0c5 100644 --- a/platform/iphone/app_delegate.mm +++ b/platform/iphone/app_delegate.mm @@ -37,6 +37,12 @@ #include "modules/FacebookScorer_ios/FacebookScorer.h" #endif +#ifdef MODULE_GAME_ANALYTICS_ENABLED +#import "modules/game_analytics/ios/MobileAppTracker.framework/Headers/MobileAppTracker.h" +//#import "modules/game_analytics/ios/MobileAppTracker.h" +#import <AdSupport/AdSupport.h> +#endif + #define kFilteringFactor 0.1 #define kRenderingFrequency 60 #define kAccelerometerFrequency 100.0 // Hz @@ -210,7 +216,36 @@ static int frame_count = 0; //OSIPhone::screen_width = rect.size.width - rect.origin.x; //OSIPhone::screen_height = rect.size.height - rect.origin.y; - mainViewController = view_controller; + mainViewController = view_controller; + +#ifdef MODULE_GAME_ANALYTICS_ENABLED + printf("********************* didFinishLaunchingWithOptions\n"); + if(!Globals::get_singleton()->has("mobileapptracker/advertiser_id")) + { + return; + } + if(!Globals::get_singleton()->has("mobileapptracker/conversion_key")) + { + return; + } + + String adid = GLOBAL_DEF("mobileapptracker/advertiser_id",""); + String convkey = GLOBAL_DEF("mobileapptracker/conversion_key",""); + + NSString * advertiser_id = [NSString stringWithUTF8String:adid.utf8().get_data()]; + NSString * conversion_key = [NSString stringWithUTF8String:convkey.utf8().get_data()]; + + // Account Configuration info - must be set + [MobileAppTracker initializeWithMATAdvertiserId:advertiser_id + MATConversionKey:conversion_key]; + + // Used to pass us the IFA, enables highly accurate 1-to-1 attribution. + // Required for many advertising networks. + [MobileAppTracker setAppleAdvertisingIdentifier:[[ASIdentifierManager sharedManager] advertisingIdentifier] + advertisingTrackingEnabled:[[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]]; + +#endif + }; - (void)applicationWillTerminate:(UIApplication*)application { @@ -240,6 +275,10 @@ static int frame_count = 0; - (void) applicationDidBecomeActive:(UIApplication *)application { printf("********************* did become active\n"); +#ifdef MODULE_GAME_ANALYTICS_ENABLED + printf("********************* mobile app tracker found\n"); + [MobileAppTracker measureSession]; +#endif [view_controller.view startAnimation]; // FIXME: resume seems to be recommended elsewhere } diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index b9e381d6ec..5b203f1560 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -98,7 +98,7 @@ public: id context; CursorShape cursor_shape; - + MouseMode mouse_mode; protected: virtual int get_video_driver_count() const; @@ -159,6 +159,8 @@ public: void run(); + void set_mouse_mode(MouseMode p_mode); + MouseMode get_mouse_mode() const; OS_OSX(); }; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index dda3527618..12f98cebe2 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -384,15 +384,10 @@ static int button_mask=0; ev.mouse_motion.y=mouse_y; ev.mouse_motion.global_x=mouse_x; ev.mouse_motion.global_y=mouse_y; - ev.mouse_motion.relative_x=mouse_x - prev_mouse_x; - ev.mouse_motion.relative_y=mouse_y - prev_mouse_y; + ev.mouse_motion.relative_x=[event deltaX] * [[event window] backingScaleFactor]; + ev.mouse_motion.relative_y=[event deltaY] * [[event window] backingScaleFactor]; ev.mouse_motion.mod = translateFlags([event modifierFlags]); - -// ev.mouse_motion.relative_x=[event deltaX]; -// ev.mouse_motion.relative_y=[event deltaY]; - - OS_OSX::singleton->input->set_mouse_pos(Point2(mouse_x,mouse_y)); OS_OSX::singleton->push_input(ev); @@ -1280,6 +1275,32 @@ void OS_OSX::run() { main_loop->finish(); } +void OS_OSX::set_mouse_mode(MouseMode p_mode) { + + if (p_mode==mouse_mode) + return; + + if (p_mode==MOUSE_MODE_CAPTURED) { + // Apple Docs state that the display parameter is not used. + // "This parameter is not used. By default, you may pass kCGDirectMainDisplay." + // https://developer.apple.com/library/mac/documentation/graphicsimaging/reference/Quartz_Services_Ref/Reference/reference.html + CGDisplayHideCursor(kCGDirectMainDisplay); + CGAssociateMouseAndMouseCursorPosition(false); + } else if (p_mode==MOUSE_MODE_HIDDEN) { + CGDisplayHideCursor(kCGDirectMainDisplay); + CGAssociateMouseAndMouseCursorPosition(true); + } else { + CGDisplayShowCursor(kCGDirectMainDisplay); + CGAssociateMouseAndMouseCursorPosition(true); + } + + mouse_mode=p_mode; +} + +OS::MouseMode OS_OSX::get_mouse_mode() const { + + return mouse_mode; +} OS_OSX* OS_OSX::singleton=NULL; |