diff options
-rw-r--r-- | drivers/gles2/rasterizer_gles2.cpp | 16 | ||||
-rw-r--r-- | drivers/gles2/shaders/material.glsl | 30 | ||||
-rw-r--r-- | platform/android/java/src/com/android/godot/Godot.java | 1 | ||||
-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 | 45 | ||||
-rw-r--r-- | platform/android/java_glue.h | 2 | ||||
-rw-r--r-- | platform/iphone/app_delegate.mm | 41 |
8 files changed, 359 insertions, 14 deletions
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 8081d8d995..dd690435ec 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -4239,9 +4239,10 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD LightInstance *li=light_instance_owner.get( liptr[i] ); if (!li || li->last_pass!=scene_pass) //lit by light not in visible scene continue; - uint8_t light_type=li->base->type; - if (li->base->shadow_enabled) + uint8_t light_type=li->base->type|0x40; //penalty to ensure directionals always go first + if (li->base->shadow_enabled) { light_type|=0x8; + } uint16_t sort_key =li->sort_key; RenderList::Element *ec; @@ -4598,7 +4599,7 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material material_shader.set_uniform(MaterialShaderGLES2::FOG_COLOR_END,Vector3(col_end.r,col_end.g,col_end.b)); } - material_shader.set_uniform(MaterialShaderGLES2::CONST_LIGHT_MULT,p_no_const_light?0.0:1.0); + //material_shader.set_uniform(MaterialShaderGLES2::TIME,Math::fmod(last_time,300.0)); //if uses TIME - draw_next_frame=true @@ -5668,7 +5669,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans case VS::MATERIAL_BLEND_MODE_ADD: { glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE); + glBlendFunc(p_alpha_pass?GL_SRC_ALPHA:GL_ONE,GL_ONE); } break; case VS::MATERIAL_BLEND_MODE_SUB: { @@ -5833,7 +5834,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans } material_shader.set_uniform(MaterialShaderGLES2::NORMAL_MULT, e->mirror?-1.0:1.0); - + material_shader.set_uniform(MaterialShaderGLES2::CONST_LIGHT_MULT,additive?0.0:1.0); _render(e->geometry, material, skeleton,e->owner,e->instance->transform); @@ -6097,6 +6098,9 @@ void RasterizerGLES2::_draw_tex_bg() { glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glColorMask(1,1,1,1); + RID texture; @@ -6132,6 +6136,7 @@ void RasterizerGLES2::_draw_tex_bg() { copy_shader.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA,true); + copy_shader.bind(); if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) { @@ -6350,6 +6355,7 @@ void RasterizerGLES2::end_scene() { _render_list_forward(&opaque_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting); if (draw_tex_background) { + //most 3D vendors recommend drawing a texture bg or skybox here, //after opaque geometry has been drawn //so the zbuffer can get rid of most pixels diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl index b667e9176c..17365ea264 100644 --- a/drivers/gles2/shaders/material.glsl +++ b/drivers/gles2/shaders/material.glsl @@ -1060,7 +1060,19 @@ LIGHT_SHADER_CODE light+=specular * light_specular * pow( eye_light, specular_exp ); } #endif - diffuse.rgb = ambient_light *diffuse.rgb + light * attenuation * shadow_attenuation; + diffuse.rgb = const_light_mult * ambient_light *diffuse.rgb + light * attenuation * shadow_attenuation; + +#ifdef USE_FOG + + diffuse.rgb = mix(diffuse.rgb,fog_interp.rgb,fog_interp.a); + +# if defined(LIGHT_TYPE_OMNI) || defined (LIGHT_TYPE_SPOT) + diffuse.rgb = mix(mix(vec3(0.0),diffuse.rgb,attenuation),diffuse.rgb,const_light_mult); +# endif + + +#endif + } @@ -1084,9 +1096,10 @@ LIGHT_SHADER_CODE #ifdef USE_VERTEX_LIGHTING - vec3 ambient = ambient_light*diffuse.rgb; + vec3 ambient = const_light_mult*ambient_light*diffuse.rgb; # if defined(LIGHT_TYPE_OMNI) || defined (LIGHT_TYPE_SPOT) ambient*=diffuse_interp.a; //attenuation affects ambient too + # endif // diffuse.rgb=(diffuse.rgb * diffuse_interp.rgb + specular * specular_interp)*shadow_attenuation + ambient; @@ -1094,6 +1107,16 @@ LIGHT_SHADER_CODE diffuse.rgb=(diffuse.rgb * diffuse_interp.rgb + specular * specular_interp)*shadow_attenuation + ambient; diffuse.rgb+=emission * const_light_mult; +#ifdef USE_FOG + + diffuse.rgb = mix(diffuse.rgb,fog_interp.rgb,fog_interp.a); + +# if defined(LIGHT_TYPE_OMNI) || defined (LIGHT_TYPE_SPOT) + diffuse.rgb = mix(mix(vec3(0.0),diffuse.rgb,diffuse_interp.a),diffuse.rgb,const_light_mult); +# endif + +#endif + #endif @@ -1120,10 +1143,7 @@ LIGHT_SHADER_CODE #else -#ifdef USE_FOG - diffuse.rgb = mix(diffuse.rgb,fog_interp.rgb,fog_interp.a); -#endif #ifdef USE_GLOW diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java index 16a5a17cbb..11fb894545 100644 --- a/platform/android/java/src/com/android/godot/Godot.java +++ b/platform/android/java/src/com/android/godot/Godot.java @@ -498,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/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 b9e13892d2..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; @@ -1279,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; 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/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 } |