godot/platform/bb10/os_bb10.cpp
2014-02-09 22:10:30 -03:00

631 lines
16 KiB
C++

/*************************************************************************/
/* os_bb10.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. */
/*************************************************************************/
#include "os_bb10.h"
#include "drivers/gles2/rasterizer_gles2.h"
#include "drivers/gles1/rasterizer_gles1.h"
#include "servers/visual/visual_server_raster.h"
#include "core/os/dir_access.h"
#include "core/globals.h"
#include "main/main.h"
#include "bbutil.h"
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include "core/os/keyboard.h"
#include "bps/bps.h"
#include "bps/screen.h"
#include "bps/navigator.h"
#include "bps/accelerometer.h"
#include "bps/orientation.h"
#include "bps/virtualkeyboard.h"
#include "bps/audiodevice.h"
#ifdef BB10_SCORELOOP_ENABLED
#include "modules/scoreloop/scoreloop_bb10.h"
#endif
static char launch_dir[512];
char* launch_dir_ptr;
int OSBB10::get_video_driver_count() const {
return 1;
}
const char * OSBB10::get_video_driver_name(int p_driver) const {
return "GLES2";
}
OS::VideoMode OSBB10::get_default_video_mode() const {
return OS::VideoMode();
}
int OSBB10::get_audio_driver_count() const {
return 1;
}
const char * OSBB10::get_audio_driver_name(int p_driver) const {
return "BB10";
}
void OSBB10::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) {
data_dir = getenv("HOME");
//Create a screen context that will be used to create an EGL surface to to receive libscreen events
screen_create_context(&screen_cxt,0);
//Initialize BPS library
bps_initialize();
//Use utility code to initialize EGL for 2D rendering with GL ES 1.1
enum RENDERING_API api = GL_ES_2;
#ifdef BB10_LGLES_OVERRIDE
api = GL_ES_1;
#endif
if (EXIT_SUCCESS != bbutil_init(screen_cxt, api)) {
bbutil_terminate();
screen_destroy_context(screen_cxt);
return;
};
EGLint surface_width, surface_height;
eglQuerySurface(egl_disp, egl_surf, EGL_WIDTH, &surface_width);
eglQuerySurface(egl_disp, egl_surf, EGL_HEIGHT, &surface_height);
printf("screen size: %ix%i\n", surface_width, surface_height);
VideoMode mode;
mode.width = surface_width;
mode.height = surface_height;
mode.fullscreen = true;
mode.resizable = false;
set_video_mode(mode);
//Signal BPS library that navigator and screen events will be requested
screen_request_events(screen_cxt);
navigator_request_events(0);
virtualkeyboard_request_events(0);
audiodevice_request_events(0);
#ifdef DEBUG_ENABLED
bps_set_verbosity(3);
#endif
accel_supported = accelerometer_is_supported();
if (accel_supported)
accelerometer_set_update_frequency(FREQ_40_HZ);
pitch = 0;
roll = 0;
#ifdef BB10_LGLES_OVERRIDE
rasterizer = memnew( RasterizerGLES1(false) );
#else
rasterizer = memnew( RasterizerGLES2(false, false) );
#endif
visual_server = memnew( VisualServerRaster(rasterizer) );
visual_server->init();
visual_server->cursor_set_visible(false, 0);
audio_driver = memnew(AudioDriverBB10);
audio_driver->set_singleton();
audio_driver->init(NULL);
sample_manager = memnew( SampleManagerMallocSW );
audio_server = memnew( AudioServerSW(sample_manager) );
audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR,false);
audio_server->init();
spatial_sound_server = memnew( SpatialSoundServerSW );
spatial_sound_server->init();
spatial_sound_2d_server = memnew( SpatialSound2DServerSW );
spatial_sound_2d_server->init();
//
physics_server = memnew( PhysicsServerSW );
physics_server->init();
physics_2d_server = memnew( Physics2DServerSW );
physics_2d_server->init();
input = memnew( InputDefault );
#ifdef PAYMENT_SERVICE_ENABLED
payment_service = memnew(PaymentService);
Globals::get_singleton()->add_singleton(Globals::Singleton("InAppStore", payment_service));
#endif
}
void OSBB10::set_main_loop( MainLoop * p_main_loop ) {
input->set_main_loop(p_main_loop);
main_loop=p_main_loop;
}
void OSBB10::delete_main_loop() {
memdelete( main_loop );
main_loop = NULL;
}
void OSBB10::finalize() {
if(main_loop)
memdelete(main_loop);
main_loop=NULL;
spatial_sound_server->finish();
memdelete(spatial_sound_server);
spatial_sound_2d_server->finish();
memdelete(spatial_sound_2d_server);
//if (debugger_connection_console) {
// memdelete(debugger_connection_console);
//}
audio_server->finish();
memdelete(audio_server);
memdelete(sample_manager);
visual_server->finish();
memdelete(visual_server);
memdelete(rasterizer);
physics_server->finish();
memdelete(physics_server);
physics_2d_server->finish();
memdelete(physics_2d_server);
#ifdef PAYMENT_SERVICE_ENABLED
memdelete(payment_service);
#endif
memdelete(input);
bbutil_terminate();
screen_destroy_context(screen_cxt);
bps_shutdown();
}
void OSBB10::set_mouse_show(bool p_show) {
//android has no mouse...
}
void OSBB10::set_mouse_grab(bool p_grab) {
//it really has no mouse...!
}
bool OSBB10::is_mouse_grab_enabled() const {
//*sigh* technology has evolved so much since i was a kid..
return false;
}
Point2 OSBB10::get_mouse_pos() const {
return Point2();
}
int OSBB10::get_mouse_button_state() const {
return 0;
}
void OSBB10::set_window_title(const String& p_title) {
}
//interesting byt not yet
//void set_clipboard(const String& p_text);
//String get_clipboard() const;
void OSBB10::set_video_mode(const VideoMode& p_video_mode,int p_screen) {
default_videomode = p_video_mode;
}
OS::VideoMode OSBB10::get_video_mode(int p_screen) const {
return default_videomode;
}
void OSBB10::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) const {
p_list->push_back(default_videomode);
}
String OSBB10::get_name() {
return "BlackBerry 10";
}
MainLoop *OSBB10::get_main_loop() const {
return main_loop;
}
bool OSBB10::can_draw() const {
return !minimized;
}
void OSBB10::set_cursor_shape(CursorShape p_shape) {
//android really really really has no mouse.. how amazing..
}
void OSBB10::handle_screen_event(bps_event_t *event) {
screen_event_t screen_event = screen_event_get_event(event);
int screen_val;
screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &screen_val);
int pos[2];
switch (screen_val) {
case SCREEN_EVENT_MTOUCH_TOUCH:
case SCREEN_EVENT_MTOUCH_RELEASE: {
screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_POSITION, pos);
InputEvent ievent;
ievent.type = InputEvent::SCREEN_TOUCH;
ievent.ID = ++last_id;
ievent.device = 0;
ievent.screen_touch.pressed = (screen_val == SCREEN_EVENT_MTOUCH_TOUCH);
ievent.screen_touch.x = pos[0];
ievent.screen_touch.y = pos[1];
Point2 mpos(ievent.screen_touch.x, ievent.screen_touch.y);
screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pos[0]);
ievent.screen_touch.index = pos[0];
last_touch_x[pos[0]] = ievent.screen_touch.x;
last_touch_y[pos[0]] = ievent.screen_touch.y;
input->parse_input_event( ievent );
if (ievent.screen_touch.index == 0) {
InputEvent ievent;
ievent.type = InputEvent::MOUSE_BUTTON;
ievent.ID = ++last_id;
ievent.device = 0;
ievent.mouse_button.pressed = (screen_val == SCREEN_EVENT_MTOUCH_TOUCH);
ievent.mouse_button.button_index = BUTTON_LEFT;
ievent.mouse_button.doubleclick = 0;
ievent.mouse_button.x = ievent.mouse_button.global_x = mpos.x;
ievent.mouse_button.y = ievent.mouse_button.global_y = mpos.y;
input->parse_input_event( ievent );
};
} break;
case SCREEN_EVENT_MTOUCH_MOVE: {
screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_POSITION, pos);
InputEvent ievent;
ievent.type = InputEvent::SCREEN_DRAG;
ievent.ID = ++last_id;
ievent.device = 0;
ievent.screen_drag.x = pos[0];
ievent.screen_drag.y = pos[1];
/*
screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, pos);
ievent.screen_drag.relative_x = ievent.screen_drag.x - pos[0];
ievent.screen_drag.relative_y = ievent.screen_drag.y - pos[1];
*/
screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pos[0]);
ievent.screen_drag.index = pos[0];
ievent.screen_drag.relative_x = ievent.screen_drag.x - last_touch_x[ievent.screen_drag.index];
ievent.screen_drag.relative_y = ievent.screen_drag.y - last_touch_y[ievent.screen_drag.index];
last_touch_x[ievent.screen_drag.index] = ievent.screen_drag.x;
last_touch_y[ievent.screen_drag.index] = ievent.screen_drag.y;
Point2 mpos(ievent.screen_drag.x, ievent.screen_drag.y);
Point2 mrel(ievent.screen_drag.relative_x, ievent.screen_drag.relative_y);
input->parse_input_event( ievent );
if (ievent.screen_touch.index == 0) {
InputEvent ievent;
ievent.type = InputEvent::MOUSE_MOTION;
ievent.ID = ++last_id;
ievent.device = 0;
ievent.mouse_motion.x = ievent.mouse_motion.global_x = mpos.x;
ievent.mouse_motion.y = ievent.mouse_motion.global_y = mpos.y;
input->set_mouse_pos(Point2(ievent.mouse_motion.x,ievent.mouse_motion.y));
ievent.mouse_motion.speed_x=input->get_mouse_speed().x;
ievent.mouse_motion.speed_y=input->get_mouse_speed().y;
ievent.mouse_motion.relative_x = mrel.x;
ievent.mouse_motion.relative_y = mrel.y;
ievent.mouse_motion.button_mask = 1; // pressed
input->parse_input_event( ievent );
};
} break;
case SCREEN_EVENT_KEYBOARD: {
InputEvent ievent;
ievent.type = InputEvent::KEY;
ievent.ID = ++last_id;
ievent.device = 0;
int val = 0;
screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SCAN, &val);
ievent.key.scancode = val;
screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &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;
};
int flags;
screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags);
ievent.key.pressed = flags & 1; // bit 1 is pressed apparently
int mod;
screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_MODIFIERS, &mod);
input->parse_input_event( ievent );
} break;
default:
break;
}
};
void OSBB10::handle_accelerometer() {
if (!accel_supported)
return;
if (!fullscreen)
return;
double force_x, force_y, force_z;
accelerometer_read_forces(&force_x, &force_y, &force_z);
Vector3 accel = Vector3(force_x, flip_accelerometer ? force_y : -force_y, force_z);
input->set_accelerometer(accel);
// rotate 90 degrees
//input->set_accelerometer(Vector3(force_y, flip_accelerometer?force_x:(-force_x), force_z));
};
void OSBB10::_resize(bps_event_t* event) {
int angle = navigator_event_get_orientation_angle(event);
bbutil_rotate_screen_surface(angle);
EGLint surface_width, surface_height;
eglQuerySurface(egl_disp, egl_surf, EGL_WIDTH, &surface_width);
eglQuerySurface(egl_disp, egl_surf, EGL_HEIGHT, &surface_height);
VideoMode mode;
mode.width = surface_width;
mode.height = surface_height;
mode.fullscreen = true;
mode.resizable = false;
set_video_mode(mode);
};
void OSBB10::process_events() {
handle_accelerometer();
bps_event_t *event = NULL;
do {
int rc = bps_get_event(&event, 0);
assert(rc == BPS_SUCCESS);
if (!event) break;
#ifdef BB10_SCORELOOP_ENABLED
ScoreloopBB10* sc = Globals::get_singleton()->get_singleton_object("Scoreloop")->cast_to<ScoreloopBB10>();
if (sc->handle_event(event))
continue;
#endif
#ifdef PAYMENT_SERVICE_ENABLED
if (payment_service->handle_event(event))
continue;
#endif
int domain = bps_event_get_domain(event);
if (domain == screen_get_domain()) {
handle_screen_event(event);
} else if (domain == navigator_get_domain()) {
if (NAVIGATOR_EXIT == bps_event_get_code(event)) {
if (main_loop)
main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST);
bps_event_destroy(event);
exit(0);
return;
/*
} else if (bps_event_get_code(event) == NAVIGATOR_ORIENTATION_CHECK) {
int angle = navigator_event_get_orientation_angle(event);
navigator_orientation_check_response(event, false);
} else if (bps_event_get_code(event) == NAVIGATOR_ORIENTATION) {
_resize(event);
*/
} else if (bps_event_get_code(event) == NAVIGATOR_WINDOW_STATE) {
int state = navigator_event_get_window_state(event);
bool was_fullscreen = fullscreen;
minimized = state == NAVIGATOR_WINDOW_INVISIBLE;
fullscreen = state == NAVIGATOR_WINDOW_FULLSCREEN;
set_low_processor_usage_mode(!fullscreen);
if (fullscreen != was_fullscreen) {
if (fullscreen) {
audio_server->set_fx_global_volume_scale(fullscreen_mixer_volume);
audio_server->set_stream_global_volume_scale(fullscreen_stream_volume);
} else {
fullscreen_mixer_volume = audio_server->get_fx_global_volume_scale();
fullscreen_stream_volume = audio_server->get_stream_global_volume_scale();
audio_server->set_fx_global_volume_scale(0);
audio_server->set_stream_global_volume_scale(0);
};
};
};
} else if (domain == audiodevice_get_domain()) {
const char * audiodevice_path = audiodevice_event_get_path(event);
printf("************* got audiodevice event, path %s\n", audiodevice_path);
audio_driver->finish();
audio_driver->init(audiodevice_path);
audio_driver->start();
};
//bps_event_destroy(event);
} while (event);
};
bool OSBB10::has_virtual_keyboard() const {
return true;
};
void OSBB10::show_virtual_keyboard(const String& p_existing_text,const Rect2& p_screen_rect) {
virtualkeyboard_show();
};
void OSBB10::hide_virtual_keyboard() {
virtualkeyboard_hide();
};
void OSBB10::run() {
if (!main_loop)
return;
main_loop->init();
int flip = bbutil_is_flipped();
int rot = bbutil_get_rotation();
flip_accelerometer = rot == 90;
printf("**************** rot is %i, flip %i\n", rot, (int)flip_accelerometer);
/*
orientation_direction_t orientation;
int angle;
orientation_get(&orientation, &angle);
printf("******************** orientation %i, %i, %i\n", orientation, ORIENTATION_BOTTOM_UP, ORIENTATION_TOP_UP);
if (orientation == ORIENTATION_BOTTOM_UP) {
flip_accelerometer = true;
};
*/
while (true) {
process_events(); // get rid of pending events
if (Main::iteration()==true)
break;
bbutil_swap();
//#ifdef DEBUG_ENABLED
fflush(stdout);
//#endif
};
main_loop->finish();
};
bool OSBB10::has_touchscreen_ui_hint() const {
return true;
}
Error OSBB10::shell_open(String p_uri) {
char* msg = NULL;
int ret = navigator_invoke(p_uri.utf8().get_data(), &msg);
return ret == BPS_SUCCESS ? OK : FAILED;
};
String OSBB10::get_data_dir() const {
return data_dir;
};
OSBB10::OSBB10() {
main_loop=NULL;
last_id=1;
minimized = false;
fullscreen = true;
flip_accelerometer = true;
fullscreen_mixer_volume = 1;
fullscreen_stream_volume = 1;
printf("godot bb10!\n");
getcwd(launch_dir, sizeof(launch_dir));
printf("launch dir %s\n", launch_dir);
chdir("app/native/assets");
launch_dir_ptr = launch_dir;
}
OSBB10::~OSBB10() {
}