1 /*************************************************************************/
2 /* os_android.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30 #include "os_android.h"
31 #include "drivers/gles2/rasterizer_gles2.h"
32
33 #include "core/io/file_access_buffered_fa.h"
34 #include "drivers/unix/dir_access_unix.h"
35 #include "drivers/unix/file_access_unix.h"
36
37 #include "main/main.h"
38 #include "servers/visual/visual_server_raster.h"
39 #include "servers/visual/visual_server_wrap_mt.h"
40
41 #include "file_access_android.h"
42
43 #include "core/globals.h"
44
45 #ifdef ANDROID_NATIVE_ACTIVITY
46 #include "dir_access_android.h"
47 #include "file_access_android.h"
48 #else
49 #include "dir_access_jandroid.h"
50 #include "file_access_jandroid.h"
51 #endif
52
get_video_driver_count() const53 int OS_Android::get_video_driver_count() const {
54
55 return 1;
56 }
57
get_video_driver_name(int p_driver) const58 const char *OS_Android::get_video_driver_name(int p_driver) const {
59
60 return "GLES2";
61 }
62
get_default_video_mode() const63 OS::VideoMode OS_Android::get_default_video_mode() const {
64
65 return OS::VideoMode();
66 }
67
get_audio_driver_count() const68 int OS_Android::get_audio_driver_count() const {
69
70 return 1;
71 }
72
get_audio_driver_name(int p_driver) const73 const char *OS_Android::get_audio_driver_name(int p_driver) const {
74
75 return "Android";
76 }
77
initialize_core()78 void OS_Android::initialize_core() {
79
80 OS_Unix::initialize_core();
81
82 #ifdef ANDROID_NATIVE_ACTIVITY
83
84 FileAccess::make_default<FileAccessAndroid>(FileAccess::ACCESS_RESOURCES);
85 FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
86 FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
87 //FileAccessBufferedFA<FileAccessUnix>::make_default();
88 DirAccess::make_default<DirAccessAndroid>(DirAccess::ACCESS_RESOURCES);
89 DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
90 DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
91
92 #else
93
94 if (use_apk_expansion)
95 FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
96 else {
97 #ifdef USE_JAVA_FILE_ACCESS
98 FileAccess::make_default<FileAccessBufferedFA<FileAccessJAndroid> >(FileAccess::ACCESS_RESOURCES);
99 #else
100 //FileAccess::make_default<FileAccessBufferedFA<FileAccessAndroid> >(FileAccess::ACCESS_RESOURCES);
101 FileAccess::make_default<FileAccessAndroid>(FileAccess::ACCESS_RESOURCES);
102 #endif
103 }
104 FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
105 FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
106 //FileAccessBufferedFA<FileAccessUnix>::make_default();
107 if (use_apk_expansion)
108 DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_RESOURCES);
109 else
110 DirAccess::make_default<DirAccessJAndroid>(DirAccess::ACCESS_RESOURCES);
111 DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
112 DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
113
114 #endif
115 }
116
set_opengl_extensions(const char * p_gl_extensions)117 void OS_Android::set_opengl_extensions(const char *p_gl_extensions) {
118
119 ERR_FAIL_COND(!p_gl_extensions);
120 gl_extensions = p_gl_extensions;
121 }
122
initialize(const VideoMode & p_desired,int p_video_driver,int p_audio_driver)123 void OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
124
125 use_gl2 = p_video_driver != 1;
126
127 if (gfx_init_func)
128 gfx_init_func(gfx_init_ud, use_gl2);
129
130 AudioDriverManagerSW::add_driver(&audio_driver_android);
131
132 RasterizerGLES2 *rasterizer_gles22 = memnew(RasterizerGLES2(false, use_reload_hooks, false, use_reload_hooks));
133 if (gl_extensions)
134 rasterizer_gles22->set_extensions(gl_extensions);
135 rasterizer = rasterizer_gles22;
136
137 rasterizer->set_force_16_bits_fbo(use_16bits_fbo);
138
139 visual_server = memnew(VisualServerRaster(rasterizer));
140 if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
141
142 visual_server = memnew(VisualServerWrapMT(visual_server, false));
143 };
144 visual_server->init();
145
146 AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
147
148 if (AudioDriverManagerSW::get_driver(p_audio_driver)->init() != OK) {
149
150 ERR_PRINT("Initializing audio failed.");
151 }
152
153 sample_manager = memnew(SampleManagerMallocSW);
154 audio_server = memnew(AudioServerSW(sample_manager));
155
156 audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR, true);
157 audio_server->init();
158
159 spatial_sound_server = memnew(SpatialSoundServerSW);
160 spatial_sound_server->init();
161
162 spatial_sound_2d_server = memnew(SpatialSound2DServerSW);
163 spatial_sound_2d_server->init();
164
165 //
166 physics_server = memnew(PhysicsServerSW);
167 physics_server->init();
168 //physics_2d_server = memnew( Physics2DServerSW );
169 physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>();
170 physics_2d_server->init();
171
172 input = memnew(InputDefault);
173 input->set_fallback_mapping("Default Android Gamepad");
174 }
175
set_main_loop(MainLoop * p_main_loop)176 void OS_Android::set_main_loop(MainLoop *p_main_loop) {
177
178 main_loop = p_main_loop;
179 input->set_main_loop(p_main_loop);
180 }
181
delete_main_loop()182 void OS_Android::delete_main_loop() {
183
184 memdelete(main_loop);
185 }
186
finalize()187 void OS_Android::finalize() {
188
189 memdelete(input);
190 }
191
vprint(const char * p_format,va_list p_list,bool p_stderr)192 void OS_Android::vprint(const char *p_format, va_list p_list, bool p_stderr) {
193
194 __android_log_vprint(p_stderr ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO, "godot", p_format, p_list);
195 }
196
print(const char * p_format,...)197 void OS_Android::print(const char *p_format, ...) {
198
199 va_list argp;
200 va_start(argp, p_format);
201 __android_log_vprint(ANDROID_LOG_INFO, "godot", p_format, argp);
202 va_end(argp);
203 }
204
alert(const String & p_alert,const String & p_title)205 void OS_Android::alert(const String &p_alert, const String &p_title) {
206
207 print("ALERT: %s\n", p_alert.utf8().get_data());
208 if (alert_func)
209 alert_func(p_alert, p_title);
210 }
211
set_mouse_show(bool p_show)212 void OS_Android::set_mouse_show(bool p_show) {
213
214 //android has no mouse...
215 }
216
set_mouse_grab(bool p_grab)217 void OS_Android::set_mouse_grab(bool p_grab) {
218
219 //it really has no mouse...!
220 }
221
is_mouse_grab_enabled() const222 bool OS_Android::is_mouse_grab_enabled() const {
223
224 //*sigh* technology has evolved so much since i was a kid..
225 return false;
226 }
227
get_mouse_pos() const228 Point2 OS_Android::get_mouse_pos() const {
229
230 return Point2();
231 }
232
get_mouse_button_state() const233 int OS_Android::get_mouse_button_state() const {
234
235 return 0;
236 }
237
set_window_title(const String & p_title)238 void OS_Android::set_window_title(const String &p_title) {
239 }
240
set_video_mode(const VideoMode & p_video_mode,int p_screen)241 void OS_Android::set_video_mode(const VideoMode &p_video_mode, int p_screen) {
242 }
243
get_video_mode(int p_screen) const244 OS::VideoMode OS_Android::get_video_mode(int p_screen) const {
245
246 return default_videomode;
247 }
248
get_fullscreen_mode_list(List<VideoMode> * p_list,int p_screen) const249 void OS_Android::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const {
250
251 p_list->push_back(default_videomode);
252 }
253
set_keep_screen_on(bool p_enabled)254 void OS_Android::set_keep_screen_on(bool p_enabled) {
255 OS::set_keep_screen_on(p_enabled);
256
257 if (set_keep_screen_on_func) {
258 set_keep_screen_on_func(p_enabled);
259 }
260 }
261
get_window_size() const262 Size2 OS_Android::get_window_size() const {
263
264 return Vector2(default_videomode.width, default_videomode.height);
265 }
266
get_name()267 String OS_Android::get_name() {
268
269 return "Android";
270 }
271
get_main_loop() const272 MainLoop *OS_Android::get_main_loop() const {
273
274 return main_loop;
275 }
276
can_draw() const277 bool OS_Android::can_draw() const {
278
279 return true; //always?
280 }
281
set_cursor_shape(CursorShape p_shape)282 void OS_Android::set_cursor_shape(CursorShape p_shape) {
283
284 //android really really really has no mouse.. how amazing..
285 }
286
set_custom_mouse_cursor(const RES & p_cursor,CursorShape p_shape,const Vector2 & p_hotspot)287 void OS_Android::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
288
289 // Since android has no mouse, we do not need to change its texture (how amazing !)
290 }
291
main_loop_begin()292 void OS_Android::main_loop_begin() {
293
294 if (main_loop)
295 main_loop->init();
296 }
297
main_loop_iterate()298 bool OS_Android::main_loop_iterate() {
299
300 if (!main_loop)
301 return false;
302 return Main::iteration();
303 }
304
main_loop_end()305 void OS_Android::main_loop_end() {
306
307 if (main_loop)
308 main_loop->finish();
309 }
310
main_loop_focusout()311 void OS_Android::main_loop_focusout() {
312
313 if (main_loop)
314 main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
315 audio_driver_android.set_pause(true);
316 }
317
main_loop_focusin()318 void OS_Android::main_loop_focusin() {
319
320 if (main_loop)
321 main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
322 audio_driver_android.set_pause(false);
323 }
324
process_joy_event(OS_Android::JoystickEvent p_event)325 void OS_Android::process_joy_event(OS_Android::JoystickEvent p_event) {
326
327 switch (p_event.type) {
328 case JOY_EVENT_BUTTON:
329 last_id = input->joy_button(last_id, p_event.device, p_event.index, p_event.pressed);
330 break;
331 case JOY_EVENT_AXIS:
332 InputDefault::JoyAxis value;
333 value.min = -1;
334 value.value = p_event.value;
335 last_id = input->joy_axis(last_id, p_event.device, p_event.index, value);
336 break;
337 case JOY_EVENT_HAT:
338 last_id = input->joy_hat(last_id, p_event.device, p_event.hat);
339 break;
340 default:
341 return;
342 }
343 }
344
process_event(InputEvent p_event)345 void OS_Android::process_event(InputEvent p_event) {
346
347 p_event.ID = last_id++;
348 input->parse_input_event(p_event);
349 }
350
process_touch(int p_what,int p_pointer,const Vector<TouchPos> & p_points)351 void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points) {
352
353 // print_line("ev: "+itos(p_what)+" pnt: "+itos(p_pointer)+" pointc: "+itos(p_points.size()));
354
355 switch (p_what) {
356 case 0: { //gesture begin
357
358 if (touch.size()) {
359 //end all if exist
360 InputEvent ev;
361 ev.type = InputEvent::MOUSE_BUTTON;
362 ev.ID = last_id++;
363 ev.mouse_button.button_index = BUTTON_LEFT;
364 ev.mouse_button.button_mask = BUTTON_MASK_LEFT;
365 ev.mouse_button.pressed = false;
366 ev.mouse_button.x = touch[0].pos.x;
367 ev.mouse_button.y = touch[0].pos.y;
368 ev.mouse_button.global_x = touch[0].pos.x;
369 ev.mouse_button.global_y = touch[0].pos.y;
370 input->parse_input_event(ev);
371
372 for (int i = 0; i < touch.size(); i++) {
373
374 InputEvent ev;
375 ev.type = InputEvent::SCREEN_TOUCH;
376 ev.ID = last_id++;
377 ev.screen_touch.index = touch[i].id;
378 ev.screen_touch.pressed = false;
379 ev.screen_touch.x = touch[i].pos.x;
380 ev.screen_touch.y = touch[i].pos.y;
381 input->parse_input_event(ev);
382 }
383 }
384
385 touch.resize(p_points.size());
386 for (int i = 0; i < p_points.size(); i++) {
387 touch[i].id = p_points[i].id;
388 touch[i].pos = p_points[i].pos;
389 }
390
391 {
392 //send mouse
393 InputEvent ev;
394 ev.type = InputEvent::MOUSE_BUTTON;
395 ev.ID = last_id++;
396 ev.mouse_button.button_index = BUTTON_LEFT;
397 ev.mouse_button.button_mask = BUTTON_MASK_LEFT;
398 ev.mouse_button.pressed = true;
399 ev.mouse_button.x = touch[0].pos.x;
400 ev.mouse_button.y = touch[0].pos.y;
401 ev.mouse_button.global_x = touch[0].pos.x;
402 ev.mouse_button.global_y = touch[0].pos.y;
403 input->set_mouse_pos(Point2(touch[0].pos.x, touch[0].pos.y));
404 last_mouse = touch[0].pos;
405 input->parse_input_event(ev);
406 }
407
408 //send touch
409 for (int i = 0; i < touch.size(); i++) {
410
411 InputEvent ev;
412 ev.type = InputEvent::SCREEN_TOUCH;
413 ev.ID = last_id++;
414 ev.screen_touch.index = touch[i].id;
415 ev.screen_touch.pressed = true;
416 ev.screen_touch.x = touch[i].pos.x;
417 ev.screen_touch.y = touch[i].pos.y;
418 input->parse_input_event(ev);
419 }
420
421 } break;
422 case 1: { //motion
423
424 if (p_points.size()) {
425 //send mouse, should look for point 0?
426 InputEvent ev;
427 ev.type = InputEvent::MOUSE_MOTION;
428 ev.ID = last_id++;
429 ev.mouse_motion.button_mask = BUTTON_MASK_LEFT;
430 ev.mouse_motion.x = p_points[0].pos.x;
431 ev.mouse_motion.y = p_points[0].pos.y;
432 input->set_mouse_pos(Point2(ev.mouse_motion.x, ev.mouse_motion.y));
433 ev.mouse_motion.speed_x = input->get_mouse_speed().x;
434 ev.mouse_motion.speed_y = input->get_mouse_speed().y;
435 ev.mouse_motion.relative_x = p_points[0].pos.x - last_mouse.x;
436 ev.mouse_motion.relative_y = p_points[0].pos.y - last_mouse.y;
437 last_mouse = p_points[0].pos;
438 input->parse_input_event(ev);
439 }
440
441 ERR_FAIL_COND(touch.size() != p_points.size());
442
443 for (int i = 0; i < touch.size(); i++) {
444
445 int idx = -1;
446 for (int j = 0; j < p_points.size(); j++) {
447
448 if (touch[i].id == p_points[j].id) {
449 idx = j;
450 break;
451 }
452 }
453
454 ERR_CONTINUE(idx == -1);
455
456 if (touch[i].pos == p_points[idx].pos)
457 continue; //no move unncesearily
458
459 InputEvent ev;
460 ev.type = InputEvent::SCREEN_DRAG;
461 ev.ID = last_id++;
462 ev.screen_drag.index = touch[i].id;
463 ev.screen_drag.x = p_points[idx].pos.x;
464 ev.screen_drag.y = p_points[idx].pos.y;
465 ev.screen_drag.relative_x = p_points[idx].pos.x - touch[i].pos.x;
466 ev.screen_drag.relative_y = p_points[idx].pos.y - touch[i].pos.y;
467 input->parse_input_event(ev);
468 touch[i].pos = p_points[idx].pos;
469 }
470
471 } break;
472 case 2: { //release
473
474 if (touch.size()) {
475 //end all if exist
476 InputEvent ev;
477 ev.type = InputEvent::MOUSE_BUTTON;
478 ev.ID = last_id++;
479 ev.mouse_button.button_index = BUTTON_LEFT;
480 ev.mouse_button.button_mask = BUTTON_MASK_LEFT;
481 ev.mouse_button.pressed = false;
482 ev.mouse_button.x = touch[0].pos.x;
483 ev.mouse_button.y = touch[0].pos.y;
484 ev.mouse_button.global_x = touch[0].pos.x;
485 ev.mouse_button.global_y = touch[0].pos.y;
486 input->set_mouse_pos(Point2(touch[0].pos.x, touch[0].pos.y));
487 input->parse_input_event(ev);
488
489 for (int i = 0; i < touch.size(); i++) {
490
491 InputEvent ev;
492 ev.type = InputEvent::SCREEN_TOUCH;
493 ev.ID = last_id++;
494 ev.screen_touch.index = touch[i].id;
495 ev.screen_touch.pressed = false;
496 ev.screen_touch.x = touch[i].pos.x;
497 ev.screen_touch.y = touch[i].pos.y;
498 input->parse_input_event(ev);
499 }
500 touch.clear();
501 }
502
503 } break;
504 case 3: { // add tuchi
505
506 ERR_FAIL_INDEX(p_pointer, p_points.size());
507
508 TouchPos tp = p_points[p_pointer];
509 touch.push_back(tp);
510
511 InputEvent ev;
512 ev.type = InputEvent::SCREEN_TOUCH;
513 ev.ID = last_id++;
514 ev.screen_touch.index = tp.id;
515 ev.screen_touch.pressed = true;
516 ev.screen_touch.x = tp.pos.x;
517 ev.screen_touch.y = tp.pos.y;
518 input->parse_input_event(ev);
519
520 } break;
521 case 4: {
522
523 for (int i = 0; i < touch.size(); i++) {
524 if (touch[i].id == p_pointer) {
525
526 InputEvent ev;
527 ev.type = InputEvent::SCREEN_TOUCH;
528 ev.ID = last_id++;
529 ev.screen_touch.index = touch[i].id;
530 ev.screen_touch.pressed = false;
531 ev.screen_touch.x = touch[i].pos.x;
532 ev.screen_touch.y = touch[i].pos.y;
533 input->parse_input_event(ev);
534 touch.remove(i);
535 i--;
536 }
537 }
538
539 } break;
540 }
541 }
542
process_accelerometer(const Vector3 & p_accelerometer)543 void OS_Android::process_accelerometer(const Vector3 &p_accelerometer) {
544
545 input->set_accelerometer(p_accelerometer);
546 }
547
process_gravitymeter(const Vector3 & p_gravitymeter)548 void OS_Android::process_gravitymeter(const Vector3 &p_gravitymeter) {
549
550 input->set_gravity(p_gravitymeter);
551 }
552
process_magnetometer(const Vector3 & p_magnetometer)553 void OS_Android::process_magnetometer(const Vector3 &p_magnetometer) {
554
555 input->set_magnetometer(p_magnetometer);
556 }
557
process_gyroscope(const Vector3 & p_gyroscope)558 void OS_Android::process_gyroscope(const Vector3 &p_gyroscope) {
559
560 input->set_gyroscope(p_gyroscope);
561 }
562
has_touchscreen_ui_hint() const563 bool OS_Android::has_touchscreen_ui_hint() const {
564
565 return true;
566 }
567
has_virtual_keyboard() const568 bool OS_Android::has_virtual_keyboard() const {
569
570 return true;
571 }
572
show_virtual_keyboard(const String & p_existing_text,const Rect2 & p_screen_rect)573 void OS_Android::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect) {
574
575 if (show_virtual_keyboard_func) {
576 show_virtual_keyboard_func(p_existing_text);
577 } else {
578
579 ERR_PRINT("Virtual keyboard not available");
580 };
581 }
582
hide_virtual_keyboard()583 void OS_Android::hide_virtual_keyboard() {
584
585 if (hide_virtual_keyboard_func) {
586
587 hide_virtual_keyboard_func();
588 } else {
589
590 ERR_PRINT("Virtual keyboard not available");
591 };
592 }
593
init_video_mode(int p_video_width,int p_video_height)594 void OS_Android::init_video_mode(int p_video_width, int p_video_height) {
595
596 default_videomode.width = p_video_width;
597 default_videomode.height = p_video_height;
598 default_videomode.fullscreen = true;
599 default_videomode.resizable = false;
600 }
601
main_loop_request_quit()602 void OS_Android::main_loop_request_quit() {
603
604 if (main_loop)
605 main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST);
606 }
607
set_display_size(Size2 p_size)608 void OS_Android::set_display_size(Size2 p_size) {
609
610 default_videomode.width = p_size.x;
611 default_videomode.height = p_size.y;
612 }
613
reload_gfx()614 void OS_Android::reload_gfx() {
615
616 if (gfx_init_func)
617 gfx_init_func(gfx_init_ud, use_gl2);
618 if (rasterizer)
619 rasterizer->reload_vram();
620 }
621
shell_open(String p_uri)622 Error OS_Android::shell_open(String p_uri) {
623
624 if (open_uri_func)
625 return open_uri_func(p_uri) ? ERR_CANT_OPEN : OK;
626 return ERR_UNAVAILABLE;
627 }
628
get_resource_dir() const629 String OS_Android::get_resource_dir() const {
630
631 return "/"; //android has it's own filesystem for resources inside the APK
632 }
633
get_locale() const634 String OS_Android::get_locale() const {
635
636 if (get_locale_func)
637 return get_locale_func();
638 return OS_Unix::get_locale();
639 }
640
set_clipboard(const String & p_text)641 void OS_Android::set_clipboard(const String &p_text) {
642
643 if (set_clipboard_func) {
644 set_clipboard_func(p_text);
645 } else {
646 OS_Unix::set_clipboard(p_text);
647 }
648 }
649
get_clipboard() const650 String OS_Android::get_clipboard() const {
651 if (get_clipboard_func) {
652 return get_clipboard_func();
653 }
654
655 return OS_Unix::get_clipboard();
656 }
657
get_model_name() const658 String OS_Android::get_model_name() const {
659
660 if (get_model_func)
661 return get_model_func();
662 return OS_Unix::get_model_name();
663 }
664
get_screen_dpi(int p_screen) const665 int OS_Android::get_screen_dpi(int p_screen) const {
666
667 if (get_screen_dpi_func) {
668 return get_screen_dpi_func();
669 }
670 return 160;
671 }
672
set_need_reload_hooks(bool p_needs_them)673 void OS_Android::set_need_reload_hooks(bool p_needs_them) {
674
675 use_reload_hooks = p_needs_them;
676 }
677
get_data_dir() const678 String OS_Android::get_data_dir() const {
679
680 if (data_dir_cache != String())
681 return data_dir_cache;
682
683 if (get_data_dir_func) {
684 String data_dir = get_data_dir_func();
685
686 //store current dir
687 char real_current_dir_name[2048];
688 getcwd(real_current_dir_name, 2048);
689
690 //go to data dir
691 chdir(data_dir.utf8().get_data());
692
693 //get actual data dir, so we resolve potential symlink (Android 6.0+ seems to use symlink)
694 char data_current_dir_name[2048];
695 getcwd(data_current_dir_name, 2048);
696
697 //cache by parsing utf8
698 data_dir_cache.parse_utf8(data_current_dir_name);
699
700 //restore original dir so we don't mess things up
701 chdir(real_current_dir_name);
702
703 return data_dir_cache;
704 }
705
706 return ".";
707 //return Globals::get_singleton()->get_singleton_object("GodotOS")->call("get_data_dir");
708 }
709
set_screen_orientation(ScreenOrientation p_orientation)710 void OS_Android::set_screen_orientation(ScreenOrientation p_orientation) {
711
712 if (set_screen_orientation_func)
713 set_screen_orientation_func(p_orientation);
714 }
715
get_unique_ID() const716 String OS_Android::get_unique_ID() const {
717
718 if (get_unique_id_func)
719 return get_unique_id_func();
720 return OS::get_unique_ID();
721 }
722
native_video_play(String p_path,float p_volume)723 Error OS_Android::native_video_play(String p_path, float p_volume) {
724 if (video_play_func)
725 video_play_func(p_path);
726 return OK;
727 }
728
native_video_is_playing()729 bool OS_Android::native_video_is_playing() {
730 if (video_is_playing_func)
731 return video_is_playing_func();
732 return false;
733 }
734
native_video_pause()735 void OS_Android::native_video_pause() {
736 if (video_pause_func)
737 video_pause_func();
738 }
739
get_system_dir(SystemDir p_dir) const740 String OS_Android::get_system_dir(SystemDir p_dir) const {
741
742 if (get_system_dir_func)
743 return get_system_dir_func(p_dir);
744 return String(".");
745 }
746
native_video_stop()747 void OS_Android::native_video_stop() {
748 if (video_stop_func)
749 video_stop_func();
750 }
751
set_context_is_16_bits(bool p_is_16)752 void OS_Android::set_context_is_16_bits(bool p_is_16) {
753
754 use_16bits_fbo = p_is_16;
755 if (rasterizer)
756 rasterizer->set_force_16_bits_fbo(p_is_16);
757 }
758
joy_connection_changed(int p_device,bool p_connected,String p_name)759 void OS_Android::joy_connection_changed(int p_device, bool p_connected, String p_name) {
760 return input->joy_connection_changed(p_device, p_connected, p_name, "");
761 }
762
is_joy_known(int p_device)763 bool OS_Android::is_joy_known(int p_device) {
764 return input->is_joy_mapped(p_device);
765 }
766
print_error(const char * p_function,const char * p_file,int p_line,const char * p_code,const char * p_rationale,ErrorType p_type)767 void OS_Android::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
768 const char *err_details;
769 if (p_rationale && p_rationale[0])
770 err_details = p_rationale;
771 else
772 err_details = p_code;
773
774 switch (p_type) {
775 case ERR_ERROR:
776 print("ERROR: %s: %s\n", p_function, err_details);
777 print(" At: %s:%i\n", p_file, p_line);
778
779 if (emit_error_signal) {
780 emit_error_signal("Error", p_function, err_details, p_file, p_line);
781 }
782 break;
783
784 case ERR_WARNING:
785 print("WARNING: %s: %s\n", p_function, err_details);
786 print(" At: %s:%i\n", p_file, p_line);
787
788 if (emit_error_signal) {
789 emit_error_signal("Warning", p_function, err_details, p_file, p_line);
790 }
791 break;
792
793 case ERR_SCRIPT:
794 print("SCRIPT ERROR: %s: %s\n", p_function, err_details);
795 print(" At: %s:%i\n", p_file, p_line);
796
797 if (emit_error_signal) {
798 emit_error_signal("Script error", p_function, err_details, p_file, p_line);
799 }
800 break;
801 }
802 }
803
get_joy_guid(int p_device) const804 String OS_Android::get_joy_guid(int p_device) const {
805 return input->get_joy_guid_remapped(p_device);
806 }
807
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,GetScreenDPIFunc p_get_screen_dpi_func,ShowVirtualKeyboardFunc p_show_vk,HideVirtualKeyboardFunc p_hide_vk,SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id,GetSystemDirFunc p_get_sdir_func,VideoPlayFunc p_video_play_func,VideoIsPlayingFunc p_video_is_playing_func,VideoPauseFunc p_video_pause_func,VideoStopFunc p_video_stop_func,SetKeepScreenOnFunc p_set_keep_screen_on_func,AlertFunc p_alert_func,bool p_use_apk_expansion,SetClipboardFunc p_set_clipboard_func,GetClipboardFunc p_get_clipboard_func,EmitErrorSignal p_emit_error_signal)808 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, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, bool p_use_apk_expansion, SetClipboardFunc p_set_clipboard_func, GetClipboardFunc p_get_clipboard_func, EmitErrorSignal p_emit_error_signal) {
809
810 use_apk_expansion = p_use_apk_expansion;
811 default_videomode.width = 800;
812 default_videomode.height = 600;
813 default_videomode.fullscreen = true;
814 default_videomode.resizable = false;
815
816 gfx_init_func = p_gfx_init_func;
817 gfx_init_ud = p_gfx_init_ud;
818 main_loop = NULL;
819 last_id = 1;
820 gl_extensions = NULL;
821 rasterizer = NULL;
822 use_gl2 = false;
823
824 open_uri_func = p_open_uri_func;
825 get_data_dir_func = p_get_data_dir_func;
826 get_locale_func = p_get_locale_func;
827 get_model_func = p_get_model_func;
828 get_screen_dpi_func = p_get_screen_dpi_func;
829 get_unique_id_func = p_get_unique_id;
830 get_system_dir_func = p_get_sdir_func;
831
832 video_play_func = p_video_play_func;
833 video_is_playing_func = p_video_is_playing_func;
834 video_pause_func = p_video_pause_func;
835 video_stop_func = p_video_stop_func;
836
837 show_virtual_keyboard_func = p_show_vk;
838 hide_virtual_keyboard_func = p_hide_vk;
839
840 set_screen_orientation_func = p_screen_orient;
841 set_keep_screen_on_func = p_set_keep_screen_on_func;
842 alert_func = p_alert_func;
843 use_reload_hooks = false;
844
845 set_clipboard_func = p_set_clipboard_func;
846 get_clipboard_func = p_get_clipboard_func;
847
848 emit_error_signal = p_emit_error_signal;
849 }
850
~OS_Android()851 OS_Android::~OS_Android() {
852 }
853