diff options
Diffstat (limited to 'platform')
-rw-r--r-- | platform/javascript/javascript_main.cpp | 148 | ||||
-rw-r--r-- | platform/javascript/os_javascript.cpp | 493 | ||||
-rw-r--r-- | platform/javascript/os_javascript.h | 26 | ||||
-rw-r--r-- | platform/uwp/SCsub | 1 | ||||
-rw-r--r-- | platform/uwp/app.h | 2 | ||||
-rw-r--r-- | platform/uwp/export/export.cpp | 9 | ||||
-rw-r--r-- | platform/uwp/os_uwp.cpp | 69 | ||||
-rw-r--r-- | platform/uwp/os_uwp.h | 7 | ||||
-rw-r--r-- | platform/uwp/power_uwp.cpp | 74 | ||||
-rw-r--r-- | platform/uwp/power_uwp.h | 55 |
10 files changed, 458 insertions, 426 deletions
diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp index ff29c21b1c..6b1d574496 100644 --- a/platform/javascript/javascript_main.cpp +++ b/platform/javascript/javascript_main.cpp @@ -31,166 +31,50 @@ #include "io/resource_loader.h" #include "main/main.h" #include "os_javascript.h" -#include <GL/glut.h> -#include <string.h> OS_JavaScript *os = NULL; -static void _gfx_init(void *ud, bool gl2, int w, int h, bool fs) { +static void main_loop() { - glutInitWindowSize(w, h); - glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); - glutCreateWindow("godot"); + os->main_loop_iterate(); } -static uint32_t _mouse_button_mask = 0; +extern "C" void main_after_fs_sync() { -static void _glut_mouse_button(int button, int state, int x, int y) { - - InputEvent ev; - ev.type = InputEvent::MOUSE_BUTTON; - switch (button) { - case GLUT_LEFT_BUTTON: ev.mouse_button.button_index = BUTTON_LEFT; break; - case GLUT_MIDDLE_BUTTON: ev.mouse_button.button_index = BUTTON_MIDDLE; break; - case GLUT_RIGHT_BUTTON: ev.mouse_button.button_index = BUTTON_RIGHT; break; - case 3: ev.mouse_button.button_index = BUTTON_WHEEL_UP; break; - case 4: ev.mouse_button.button_index = BUTTON_WHEEL_DOWN; break; - } - - ev.mouse_button.pressed = state == GLUT_DOWN; - ev.mouse_button.x = x; - ev.mouse_button.y = y; - ev.mouse_button.global_x = x; - ev.mouse_button.global_y = y; - - if (ev.mouse_button.button_index < 4) { - if (ev.mouse_button.pressed) { - _mouse_button_mask |= 1 << (ev.mouse_button.button_index - 1); - } else { - _mouse_button_mask &= ~(1 << (ev.mouse_button.button_index - 1)); - } - } - ev.mouse_button.button_mask = _mouse_button_mask; - - uint32_t m = glutGetModifiers(); - ev.mouse_button.mod.alt = (m & GLUT_ACTIVE_ALT) != 0; - ev.mouse_button.mod.shift = (m & GLUT_ACTIVE_SHIFT) != 0; - ev.mouse_button.mod.control = (m & GLUT_ACTIVE_CTRL) != 0; - - os->push_input(ev); - - if (ev.mouse_button.button_index == BUTTON_WHEEL_UP || ev.mouse_button.button_index == BUTTON_WHEEL_DOWN) { - // GLUT doesn't send release events for mouse wheel, so send manually - ev.mouse_button.pressed = false; - os->push_input(ev); - } -} - -static int _glut_prev_x = 0; -static int _glut_prev_y = 0; - -static void _glut_mouse_motion(int x, int y) { - - InputEvent ev; - ev.type = InputEvent::MOUSE_MOTION; - ev.mouse_motion.button_mask = _mouse_button_mask; - ev.mouse_motion.x = x; - ev.mouse_motion.y = y; - ev.mouse_motion.global_x = x; - ev.mouse_motion.global_y = y; - ev.mouse_motion.relative_x = x - _glut_prev_x; - ev.mouse_motion.relative_y = y - _glut_prev_y; - _glut_prev_x = x; - _glut_prev_y = y; - - uint32_t m = glutGetModifiers(); - ev.mouse_motion.mod.alt = (m & GLUT_ACTIVE_ALT) != 0; - ev.mouse_motion.mod.shift = (m & GLUT_ACTIVE_SHIFT) != 0; - ev.mouse_motion.mod.control = (m & GLUT_ACTIVE_CTRL) != 0; - - os->push_input(ev); -} - -static void _gfx_idle() { - - glutPostRedisplay(); -} - -int start_step = 0; - -static void _godot_draw(void) { - - if (start_step == 1) { - start_step = 2; - Main::start(); - os->main_loop_begin(); - } - - if (start_step == 2) { - os->main_loop_iterate(); - } - - glutSwapBuffers(); -} - -extern "C" { - -void main_after_fs_sync() { - - start_step = 1; -} + // Ease up compatibility + ResourceLoader::set_abort_on_missing_resources(false); + Main::start(); + os->main_loop_begin(); + emscripten_set_main_loop(main_loop, 0, false); } int main(int argc, char *argv[]) { - /* Initialize the window */ printf("let it go dude!\n"); - glutInit(&argc, argv); - os = new OS_JavaScript(argv[0], _gfx_init, NULL, NULL); - Error err = Main::setup(argv[0], argc - 1, &argv[1]); - - ResourceLoader::set_abort_on_missing_resources(false); //ease up compatibility - - glutMouseFunc(_glut_mouse_button); - glutMotionFunc(_glut_mouse_motion); - glutPassiveMotionFunc(_glut_mouse_motion); - - /* Set up glut callback functions */ - glutIdleFunc(_gfx_idle); - // glutReshapeFunc(gears_reshape); - glutDisplayFunc(_godot_draw); - //glutSpecialFunc(gears_special); - - //mount persistent file system + // sync from persistent state into memory and then + // run the 'main_after_fs_sync' function /* clang-format off */ EM_ASM( + Module.noExitRuntime = true; FS.mkdir('/userfs'); FS.mount(IDBFS, {}, '/userfs'); - - // sync from persistent state into memory and then - // run the 'main_after_fs_sync' function FS.syncfs(true, function(err) { - if (err) { Module.setStatus('Failed to load persistent data\nPlease allow (third-party) cookies'); Module.printErr('Failed to populate IDB file system: ' + err.message); - Module.exit(); + Module.noExitRuntime = false; } else { Module.print('Successfully populated IDB file system'); - ccall('main_after_fs_sync', 'void', []); + ccall('main_after_fs_sync', null); } }); ); /* clang-format on */ - glutMainLoop(); + os = new OS_JavaScript(argv[0], NULL); + Error err = Main::setup(argv[0], argc - 1, &argv[1]); return 0; + // continued async in main_after_fs_sync() from syncfs() callback } - -/* - * - *09] <azakai|2__> reduz: yes, define TOTAL_MEMORY on Module. for example var Module = { TOTAL_MEMORY: 12345.. }; before the main - * - */ diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 71754502cb..1cd1991608 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -41,6 +41,21 @@ #include <emscripten.h> #include <stdlib.h> +#define DOM_BUTTON_LEFT 0 +#define DOM_BUTTON_MIDDLE 1 +#define DOM_BUTTON_RIGHT 2 + +template <typename T> +static InputModifierState dom2godot_mod(T emscripten_event_ptr) { + + InputModifierState mod; + mod.shift = emscripten_event_ptr->shiftKey; + mod.alt = emscripten_event_ptr->altKey; + mod.control = emscripten_event_ptr->ctrlKey; + mod.meta = emscripten_event_ptr->metaKey; + return mod; +} + int OS_JavaScript::get_video_driver_count() const { return 1; @@ -130,15 +145,188 @@ static EM_BOOL _fullscreen_change_callback(int event_type, const EmscriptenFulls return false; } +static InputDefault *_input; + +static EM_BOOL _mousebutton_callback(int event_type, const EmscriptenMouseEvent *mouse_event, void *user_data) { + + ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_MOUSEDOWN && event_type != EMSCRIPTEN_EVENT_MOUSEUP, false); + + InputEvent ev; + ev.type = InputEvent::MOUSE_BUTTON; + ev.mouse_button.pressed = event_type == EMSCRIPTEN_EVENT_MOUSEDOWN; + ev.mouse_button.global_x = ev.mouse_button.x = mouse_event->canvasX; + ev.mouse_button.global_y = ev.mouse_button.y = mouse_event->canvasY; + ev.mouse_button.mod = dom2godot_mod(mouse_event); + + switch (mouse_event->button) { + case DOM_BUTTON_LEFT: ev.mouse_button.button_index = BUTTON_LEFT; break; + case DOM_BUTTON_MIDDLE: ev.mouse_button.button_index = BUTTON_MIDDLE; break; + case DOM_BUTTON_RIGHT: ev.mouse_button.button_index = BUTTON_RIGHT; break; + default: return false; + } + + ev.mouse_button.button_mask = _input->get_mouse_button_mask(); + if (ev.mouse_button.pressed) + ev.mouse_button.button_mask |= 1 << ev.mouse_button.button_index; + else + ev.mouse_button.button_mask &= ~(1 << ev.mouse_button.button_index); + ev.mouse_button.button_mask >>= 1; + + _input->parse_input_event(ev); + return true; +} + +static EM_BOOL _mousemove_callback(int event_type, const EmscriptenMouseEvent *mouse_event, void *user_data) { + + ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_MOUSEMOVE, false); + + InputEvent ev; + ev.type = InputEvent::MOUSE_MOTION; + ev.mouse_motion.mod = dom2godot_mod(mouse_event); + ev.mouse_motion.button_mask = _input->get_mouse_button_mask() >> 1; + + ev.mouse_motion.global_x = ev.mouse_motion.x = mouse_event->canvasX; + ev.mouse_motion.global_y = ev.mouse_motion.y = mouse_event->canvasY; + + ev.mouse_motion.relative_x = _input->get_mouse_position().x - ev.mouse_motion.x; + ev.mouse_motion.relative_y = _input->get_mouse_position().y - ev.mouse_motion.y; + + _input->set_mouse_position(Point2(ev.mouse_motion.x, ev.mouse_motion.y)); + ev.mouse_motion.speed_x = _input->get_last_mouse_speed().x; + ev.mouse_motion.speed_y = _input->get_last_mouse_speed().y; + + _input->parse_input_event(ev); + return true; +} + +static EM_BOOL _wheel_callback(int event_type, const EmscriptenWheelEvent *wheel_event, void *user_data) { + + ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_WHEEL, false); + + InputEvent ev; + ev.type = InputEvent::MOUSE_BUTTON; + ev.mouse_button.button_mask = _input->get_mouse_button_mask() >> 1; + ev.mouse_button.global_x = ev.mouse_button.x = _input->get_mouse_position().x; + ev.mouse_button.global_y = ev.mouse_button.y = _input->get_mouse_position().y; + ev.mouse_button.mod.shift = _input->is_key_pressed(KEY_SHIFT); + ev.mouse_button.mod.alt = _input->is_key_pressed(KEY_ALT); + ev.mouse_button.mod.control = _input->is_key_pressed(KEY_CONTROL); + ev.mouse_button.mod.meta = _input->is_key_pressed(KEY_META); + + if (wheel_event->deltaY < 0) + ev.mouse_button.button_index = BUTTON_WHEEL_UP; + else if (wheel_event->deltaY > 0) + ev.mouse_button.button_index = BUTTON_WHEEL_DOWN; + else if (wheel_event->deltaX > 0) + ev.mouse_button.button_index = BUTTON_WHEEL_LEFT; + else if (wheel_event->deltaX < 0) + ev.mouse_button.button_index = BUTTON_WHEEL_RIGHT; + else + return false; + + ev.mouse_button.pressed = true; + _input->parse_input_event(ev); + + ev.mouse_button.pressed = false; + _input->parse_input_event(ev); + + return true; +} + +static Point2 _prev_touches[32]; + +static EM_BOOL _touchpress_callback(int event_type, const EmscriptenTouchEvent *touch_event, void *user_data) { + + ERR_FAIL_COND_V( + event_type != EMSCRIPTEN_EVENT_TOUCHSTART && + event_type != EMSCRIPTEN_EVENT_TOUCHEND && + event_type != EMSCRIPTEN_EVENT_TOUCHCANCEL, + false); + + InputEvent ev; + ev.type = InputEvent::SCREEN_TOUCH; + int lowest_id_index = -1; + for (int i = 0; i < touch_event->numTouches; ++i) { + + const EmscriptenTouchPoint &touch = touch_event->touches[i]; + if (lowest_id_index == -1 || touch.identifier < touch_event->touches[lowest_id_index].identifier) + lowest_id_index = i; + if (!touch.isChanged) + continue; + ev.screen_touch.index = touch.identifier; + _prev_touches[i].x = ev.screen_touch.x = touch.canvasX; + _prev_touches[i].y = ev.screen_touch.y = touch.canvasY; + ev.screen_touch.pressed = event_type == EMSCRIPTEN_EVENT_TOUCHSTART; + + _input->parse_input_event(ev); + } + + if (touch_event->touches[lowest_id_index].isChanged) { + + ev.type = InputEvent::MOUSE_BUTTON; + ev.mouse_button.mod = dom2godot_mod(touch_event); + ev.mouse_button.button_mask = _input->get_mouse_button_mask() >> 1; + ev.mouse_button.global_x = ev.mouse_button.x = touch_event->touches[lowest_id_index].canvasX; + ev.mouse_button.global_y = ev.mouse_button.y = touch_event->touches[lowest_id_index].canvasY; + ev.mouse_button.button_index = BUTTON_LEFT; + ev.mouse_button.pressed = event_type == EMSCRIPTEN_EVENT_TOUCHSTART; + + _input->parse_input_event(ev); + } + return true; +} + +static EM_BOOL _touchmove_callback(int event_type, const EmscriptenTouchEvent *touch_event, void *user_data) { + + ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_TOUCHMOVE, false); + + InputEvent ev; + ev.type = InputEvent::SCREEN_DRAG; + int lowest_id_index = -1; + for (int i = 0; i < touch_event->numTouches; ++i) { + + const EmscriptenTouchPoint &touch = touch_event->touches[i]; + if (lowest_id_index == -1 || touch.identifier < touch_event->touches[lowest_id_index].identifier) + lowest_id_index = i; + if (!touch.isChanged) + continue; + ev.screen_drag.index = touch.identifier; + ev.screen_drag.x = touch.canvasX; + ev.screen_drag.y = touch.canvasY; + Point2 &prev = _prev_touches[i]; + ev.screen_drag.relative_x = touch.canvasX - prev.x; + ev.screen_drag.relative_y = touch.canvasY - prev.y; + prev.x = ev.screen_drag.x; + prev.y = ev.screen_drag.y; + + _input->parse_input_event(ev); + } + + if (touch_event->touches[lowest_id_index].isChanged) { + + ev.type = InputEvent::MOUSE_MOTION; + ev.mouse_motion.mod = dom2godot_mod(touch_event); + ev.mouse_motion.button_mask = _input->get_mouse_button_mask() >> 1; + ev.mouse_motion.global_x = ev.mouse_motion.x = touch_event->touches[lowest_id_index].canvasX; + ev.mouse_motion.global_y = ev.mouse_motion.y = touch_event->touches[lowest_id_index].canvasY; + ev.mouse_motion.relative_x = _input->get_mouse_position().x - ev.mouse_motion.x; + ev.mouse_motion.relative_y = _input->get_mouse_position().y - ev.mouse_motion.y; + + _input->set_mouse_position(Point2(ev.mouse_motion.x, ev.mouse_motion.y)); + ev.mouse_motion.speed_x = _input->get_last_mouse_speed().x; + ev.mouse_motion.speed_y = _input->get_last_mouse_speed().y; + + _input->parse_input_event(ev); + } + return true; +} + static InputEvent _setup_key_event(const EmscriptenKeyboardEvent *emscripten_event) { InputEvent ev; ev.type = InputEvent::KEY; ev.key.echo = emscripten_event->repeat; - ev.key.mod.alt = emscripten_event->altKey; - ev.key.mod.shift = emscripten_event->shiftKey; - ev.key.mod.control = emscripten_event->ctrlKey; - ev.key.mod.meta = emscripten_event->metaKey; + ev.key.mod = dom2godot_mod(emscripten_event); ev.key.scancode = dom2godot_scancode(emscripten_event->keyCode); String unicode = String::utf8(emscripten_event->key); @@ -167,7 +355,7 @@ static EM_BOOL _keydown_callback(int event_type, const EmscriptenKeyboardEvent * deferred_key_event = ev; return false; // do not suppress keypress event } - static_cast<OS_JavaScript *>(user_data)->push_input(ev); + _input->parse_input_event(ev); return true; } @@ -176,7 +364,7 @@ static EM_BOOL _keypress_callback(int event_type, const EmscriptenKeyboardEvent ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_KEYPRESS, false); deferred_key_event.key.unicode = key_event->charCode; - static_cast<OS_JavaScript *>(user_data)->push_input(deferred_key_event); + _input->parse_input_event(deferred_key_event); return true; } @@ -186,7 +374,7 @@ static EM_BOOL _keyup_callback(int event_type, const EmscriptenKeyboardEvent *ke InputEvent ev = _setup_key_event(key_event); ev.key.pressed = false; - static_cast<OS_JavaScript *>(user_data)->push_input(ev); + _input->parse_input_event(ev); return ev.key.scancode != KEY_UNKNOWN && ev.key.scancode != 0; } @@ -202,14 +390,18 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i print_line("Init OS"); - if (gfx_init_func) - gfx_init_func(gfx_init_ud, use_gl2, p_desired.width, p_desired.height, p_desired.fullscreen); + EmscriptenWebGLContextAttributes attributes; + emscripten_webgl_init_context_attributes(&attributes); + attributes.alpha = false; + attributes.antialias = false; + attributes.majorVersion = 2; + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(NULL, &attributes); + ERR_FAIL_COND(emscripten_webgl_make_context_current(ctx) != EMSCRIPTEN_RESULT_SUCCESS); - // nothing to do here, can't fulfil fullscreen request due to - // browser security, window size is already set from HTML video_mode = p_desired; + // can't fulfil fullscreen request due to browser security video_mode.fullscreen = false; - _windowed_size = get_window_size(); + set_window_size(Size2(p_desired.width, p_desired.height)); // find locale, emscripten only sets "C" char locale_ptr[16]; @@ -257,25 +449,34 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i physics_2d_server->init(); input = memnew(InputDefault); + _input = input; power_manager = memnew(PowerJavascript); #define EM_CHECK(ev) \ if (result != EMSCRIPTEN_RESULT_SUCCESS) \ ERR_PRINTS("Error while setting " #ev " callback: Code " + itos(result)) -#define SET_EM_CALLBACK(ev, cb) \ - result = emscripten_set_##ev##_callback(NULL, this, true, &cb); \ +#define SET_EM_CALLBACK(target, ev, cb) \ + result = emscripten_set_##ev##_callback(target, this, true, &cb); \ EM_CHECK(ev) #define SET_EM_CALLBACK_NODATA(ev, cb) \ result = emscripten_set_##ev##_callback(NULL, true, &cb); \ EM_CHECK(ev) EMSCRIPTEN_RESULT result; - SET_EM_CALLBACK(keydown, _keydown_callback) - SET_EM_CALLBACK(keypress, _keypress_callback) - SET_EM_CALLBACK(keyup, _keyup_callback) - SET_EM_CALLBACK(resize, _browser_resize_callback) - SET_EM_CALLBACK(fullscreenchange, _fullscreen_change_callback) + SET_EM_CALLBACK("#canvas", mousemove, _mousemove_callback) + SET_EM_CALLBACK("#canvas", mousedown, _mousebutton_callback) + SET_EM_CALLBACK("#canvas", mouseup, _mousebutton_callback) + SET_EM_CALLBACK("#canvas", wheel, _wheel_callback) + SET_EM_CALLBACK("#canvas", touchstart, _touchpress_callback) + SET_EM_CALLBACK("#canvas", touchmove, _touchmove_callback) + SET_EM_CALLBACK("#canvas", touchend, _touchpress_callback) + SET_EM_CALLBACK("#canvas", touchcancel, _touchpress_callback) + SET_EM_CALLBACK(NULL, keydown, _keydown_callback) + SET_EM_CALLBACK(NULL, keypress, _keypress_callback) + SET_EM_CALLBACK(NULL, keyup, _keyup_callback) + SET_EM_CALLBACK(NULL, resize, _browser_resize_callback) + SET_EM_CALLBACK(NULL, fullscreenchange, _fullscreen_change_callback) SET_EM_CALLBACK_NODATA(gamepadconnected, joy_callback_func) SET_EM_CALLBACK_NODATA(gamepaddisconnected, joy_callback_func) @@ -316,20 +517,62 @@ void OS_JavaScript::alert(const String &p_alert, const String &p_title) { /* clang-format on */ } -void OS_JavaScript::set_mouse_show(bool p_show) { +void OS_JavaScript::set_css_cursor(const char *p_cursor) { - //javascript has no mouse... + /* clang-format off */ + EM_ASM_({ + Module.canvas.style.cursor = Module.UTF8ToString($0); + }, p_cursor); + /* clang-format on */ } -void OS_JavaScript::set_mouse_grab(bool p_grab) { +const char *OS_JavaScript::get_css_cursor() const { - //it really has no mouse...! + char cursor[16]; + /* clang-format off */ + EM_ASM_INT({ + Module.stringToUTF8(Module.canvas.style.cursor ? Module.canvas.style.cursor : 'auto', $0, 16); + }, cursor); + /* clang-format on */ + return cursor; } -bool OS_JavaScript::is_mouse_grab_enabled() const { +void OS_JavaScript::set_mouse_mode(OS::MouseMode p_mode) { - //*sigh* technology has evolved so much since i was a kid.. - return false; + ERR_FAIL_INDEX(p_mode, MOUSE_MODE_CONFINED + 1); + ERR_EXPLAIN("MOUSE_MODE_CONFINED is not supported for the HTML5 platform"); + ERR_FAIL_COND(p_mode == MOUSE_MODE_CONFINED); + if (p_mode == get_mouse_mode()) + return; + + if (p_mode == MOUSE_MODE_VISIBLE) { + + set_css_cursor("auto"); + emscripten_exit_pointerlock(); + + } else if (p_mode == MOUSE_MODE_HIDDEN) { + + set_css_cursor("none"); + emscripten_exit_pointerlock(); + + } else if (p_mode == MOUSE_MODE_CAPTURED) { + + EMSCRIPTEN_RESULT result = emscripten_request_pointerlock("canvas", false); + ERR_EXPLAIN("MOUSE_MODE_CAPTURED can only be entered from within an appropriate input callback"); + ERR_FAIL_COND(result == EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED); + ERR_FAIL_COND(result != EMSCRIPTEN_RESULT_SUCCESS); + set_css_cursor("auto"); + } +} + +OS::MouseMode OS_JavaScript::get_mouse_mode() const { + + if (!strcmp(get_css_cursor(), "none")) + return MOUSE_MODE_HIDDEN; + + EmscriptenPointerlockChangeEvent ev; + emscripten_get_pointerlock_status(&ev); + return ev.isActive && (strcmp(ev.id, "canvas") == 0) ? MOUSE_MODE_CAPTURED : MOUSE_MODE_VISIBLE; } Point2 OS_JavaScript::get_mouse_position() const { @@ -339,7 +582,7 @@ Point2 OS_JavaScript::get_mouse_position() const { int OS_JavaScript::get_mouse_button_state() const { - return last_button_mask; + return input->get_mouse_button_mask(); } void OS_JavaScript::set_window_title(const String &p_title) { @@ -518,197 +761,6 @@ void OS_JavaScript::main_loop_focusin() { //audio_driver_javascript.set_pause(false); } -void OS_JavaScript::push_input(const InputEvent &p_ev) { - - InputEvent ev = p_ev; - if (ev.type == InputEvent::MOUSE_MOTION) { - input->set_mouse_position(Point2(ev.mouse_motion.x, ev.mouse_motion.y)); - } else if (ev.type == InputEvent::MOUSE_BUTTON) { - last_button_mask = ev.mouse_button.button_mask; - } - input->parse_input_event(p_ev); -} - -void OS_JavaScript::process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points) { - - //print_line("ev: "+itos(p_what)+" pnt: "+itos(p_pointer)+" pointc: "+itos(p_points.size())); - - switch (p_what) { - case 0: { //gesture begin - - if (touch.size()) { - //end all if exist - InputEvent ev; - ev.type = InputEvent::MOUSE_BUTTON; - ev.mouse_button.button_index = BUTTON_LEFT; - ev.mouse_button.button_mask = BUTTON_MASK_LEFT; - ev.mouse_button.pressed = false; - ev.mouse_button.x = touch[0].pos.x; - ev.mouse_button.y = touch[0].pos.y; - ev.mouse_button.global_x = touch[0].pos.x; - ev.mouse_button.global_y = touch[0].pos.y; - input->parse_input_event(ev); - - for (int i = 0; i < touch.size(); i++) { - - InputEvent ev; - ev.type = InputEvent::SCREEN_TOUCH; - ev.screen_touch.index = touch[i].id; - ev.screen_touch.pressed = false; - ev.screen_touch.x = touch[i].pos.x; - ev.screen_touch.y = touch[i].pos.y; - input->parse_input_event(ev); - } - } - - touch.resize(p_points.size()); - for (int i = 0; i < p_points.size(); i++) { - touch[i].id = p_points[i].id; - touch[i].pos = p_points[i].pos; - } - - { - //send mouse - InputEvent ev; - ev.type = InputEvent::MOUSE_BUTTON; - ev.mouse_button.button_index = BUTTON_LEFT; - ev.mouse_button.button_mask = BUTTON_MASK_LEFT; - ev.mouse_button.pressed = true; - ev.mouse_button.x = touch[0].pos.x; - ev.mouse_button.y = touch[0].pos.y; - ev.mouse_button.global_x = touch[0].pos.x; - ev.mouse_button.global_y = touch[0].pos.y; - last_mouse = touch[0].pos; - input->parse_input_event(ev); - } - - //send touch - for (int i = 0; i < touch.size(); i++) { - - InputEvent ev; - ev.type = InputEvent::SCREEN_TOUCH; - ev.screen_touch.index = touch[i].id; - ev.screen_touch.pressed = true; - ev.screen_touch.x = touch[i].pos.x; - ev.screen_touch.y = touch[i].pos.y; - input->parse_input_event(ev); - } - - } break; - case 1: { //motion - - if (p_points.size()) { - //send mouse, should look for point 0? - InputEvent ev; - ev.type = InputEvent::MOUSE_MOTION; - ev.mouse_motion.button_mask = BUTTON_MASK_LEFT; - ev.mouse_motion.x = p_points[0].pos.x; - ev.mouse_motion.y = p_points[0].pos.y; - input->set_mouse_position(Point2(ev.mouse_motion.x, ev.mouse_motion.y)); - ev.mouse_motion.speed_x = input->get_last_mouse_speed().x; - ev.mouse_motion.speed_y = input->get_last_mouse_speed().y; - ev.mouse_motion.relative_x = p_points[0].pos.x - last_mouse.x; - ev.mouse_motion.relative_y = p_points[0].pos.y - last_mouse.y; - last_mouse = p_points[0].pos; - input->parse_input_event(ev); - } - - ERR_FAIL_COND(touch.size() != p_points.size()); - - for (int i = 0; i < touch.size(); i++) { - - int idx = -1; - for (int j = 0; j < p_points.size(); j++) { - - if (touch[i].id == p_points[j].id) { - idx = j; - break; - } - } - - ERR_CONTINUE(idx == -1); - - if (touch[i].pos == p_points[idx].pos) - continue; //no move unncesearily - - InputEvent ev; - ev.type = InputEvent::SCREEN_DRAG; - ev.screen_drag.index = touch[i].id; - ev.screen_drag.x = p_points[idx].pos.x; - ev.screen_drag.y = p_points[idx].pos.y; - ev.screen_drag.relative_x = p_points[idx].pos.x - touch[i].pos.x; - ev.screen_drag.relative_y = p_points[idx].pos.y - touch[i].pos.y; - input->parse_input_event(ev); - touch[i].pos = p_points[idx].pos; - } - - } break; - case 2: { //release - - if (touch.size()) { - //end all if exist - InputEvent ev; - ev.type = InputEvent::MOUSE_BUTTON; - ev.mouse_button.button_index = BUTTON_LEFT; - ev.mouse_button.button_mask = BUTTON_MASK_LEFT; - ev.mouse_button.pressed = false; - ev.mouse_button.x = touch[0].pos.x; - ev.mouse_button.y = touch[0].pos.y; - ev.mouse_button.global_x = touch[0].pos.x; - ev.mouse_button.global_y = touch[0].pos.y; - input->parse_input_event(ev); - - for (int i = 0; i < touch.size(); i++) { - - InputEvent ev; - ev.type = InputEvent::SCREEN_TOUCH; - ev.screen_touch.index = touch[i].id; - ev.screen_touch.pressed = false; - ev.screen_touch.x = touch[i].pos.x; - ev.screen_touch.y = touch[i].pos.y; - input->parse_input_event(ev); - } - touch.clear(); - } - - } break; - case 3: { // add tuchi - - ERR_FAIL_INDEX(p_pointer, p_points.size()); - - TouchPos tp = p_points[p_pointer]; - touch.push_back(tp); - - InputEvent ev; - ev.type = InputEvent::SCREEN_TOUCH; - ev.screen_touch.index = tp.id; - ev.screen_touch.pressed = true; - ev.screen_touch.x = tp.pos.x; - ev.screen_touch.y = tp.pos.y; - input->parse_input_event(ev); - - } break; - case 4: { - - for (int i = 0; i < touch.size(); i++) { - if (touch[i].id == p_pointer) { - - InputEvent ev; - ev.type = InputEvent::SCREEN_TOUCH; - ev.screen_touch.index = touch[i].id; - ev.screen_touch.pressed = false; - ev.screen_touch.x = touch[i].pos.x; - ev.screen_touch.y = touch[i].pos.y; - input->parse_input_event(ev); - touch.remove(i); - i--; - } - } - - } break; - } -} - void OS_JavaScript::process_accelerometer(const Vector3 &p_accelerometer) { input->set_accelerometer(p_accelerometer); @@ -829,11 +881,8 @@ int OS_JavaScript::get_power_percent_left() { return power_manager->get_power_percent_left(); } -OS_JavaScript::OS_JavaScript(const char *p_execpath, GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, GetDataDirFunc p_get_data_dir_func) { +OS_JavaScript::OS_JavaScript(const char *p_execpath, GetDataDirFunc p_get_data_dir_func) { set_cmdline(p_execpath, get_cmdline_args()); - gfx_init_func = p_gfx_init_func; - gfx_init_ud = p_gfx_init_ud; - last_button_mask = 0; main_loop = NULL; gl_extensions = NULL; window_maximized = false; diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index ea906c560f..ffd269b512 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -45,24 +45,9 @@ #include <emscripten/html5.h> -typedef void (*GFXInitFunc)(void *ud, bool gl2, int w, int h, bool fs); typedef String (*GetDataDirFunc)(); class OS_JavaScript : public OS_Unix { -public: - struct TouchPos { - int id; - Point2 pos; - }; - -private: - Vector<TouchPos> touch; - Point2 last_mouse; - int last_button_mask; - GFXInitFunc gfx_init_func; - void *gfx_init_ud; - - bool use_gl2; int64_t time_to_save_sync; int64_t last_sync_time; @@ -90,6 +75,9 @@ private: void process_joypads(); + void set_css_cursor(const char *); + const char *get_css_cursor() const; + public: // functions used by main to initialize/deintialize the OS virtual int get_video_driver_count() const; @@ -119,9 +107,8 @@ public: virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); - virtual void set_mouse_show(bool p_show); - virtual void set_mouse_grab(bool p_grab); - virtual bool is_mouse_grab_enabled() const; + virtual void set_mouse_mode(MouseMode p_mode); + virtual MouseMode get_mouse_mode() const; virtual Point2 get_mouse_position() const; virtual int get_mouse_button_state() const; virtual void set_window_title(const String &p_title); @@ -166,7 +153,6 @@ public: virtual String get_resource_dir() const; void process_accelerometer(const Vector3 &p_accelerometer); - void process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points); void push_input(const InputEvent &p_ev); virtual bool is_joy_known(int p_device); @@ -177,7 +163,7 @@ public: virtual int get_power_seconds_left(); virtual int get_power_percent_left(); - OS_JavaScript(const char *p_execpath, GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, GetDataDirFunc p_get_data_dir_func); + OS_JavaScript(const char *p_execpath, GetDataDirFunc p_get_data_dir_func); ~OS_JavaScript(); }; diff --git a/platform/uwp/SCsub b/platform/uwp/SCsub index 0167ea9e02..7ee5aa2ac3 100644 --- a/platform/uwp/SCsub +++ b/platform/uwp/SCsub @@ -9,6 +9,7 @@ files = [ '#platform/windows/stream_peer_winsock.cpp', '#platform/windows/key_mapping_win.cpp', 'joypad_uwp.cpp', + 'power_uwp.cpp', 'gl_context_egl.cpp', 'app.cpp', 'os_uwp.cpp', diff --git a/platform/uwp/app.h b/platform/uwp/app.h index 647ef0261b..9cbe7669c9 100644 --- a/platform/uwp/app.h +++ b/platform/uwp/app.h @@ -107,7 +107,7 @@ namespace GodotUWP int last_touch_y[32]; int number_of_contacts; Windows::Foundation::Point last_mouse_pos; - } + }; } /* clang-format on */ diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index 4a164e5ba1..976e6208ee 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -72,17 +72,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "editor/editor_import_export.h" #include "editor/editor_node.h" #include "global_config.h" -#include "io/base64.h" #include "io/marshalls.h" -#include "io/sha256.h" -#include "io/unzip.h" -#include "io/zip.h" #include "io/zip_io.h" #include "object.h" #include "os/file_access.h" #include "platform/uwp/logo.h" #include "version.h" +#include "thirdparty/minizip/unzip.h" +#include "thirdparty/minizip/zip.h" +#include "thirdparty/misc/base64.h" +#include "thirdparty/misc/sha256.h" + #include <zlib.h> // Capabilities diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 8b7e821ab3..818b827e83 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -28,24 +28,22 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "os_uwp.h" -#include "drivers/gles2/rasterizer_gles2.h" +#include "drivers/gles3/rasterizer_gles3.h" +#include "drivers/unix/ip_unix.h" #include "drivers/windows/dir_access_windows.h" #include "drivers/windows/file_access_windows.h" #include "drivers/windows/mutex_windows.h" +#include "drivers/windows/rw_lock_windows.h" #include "drivers/windows/semaphore_windows.h" -#include "main/main.h" -#include "os/memory_pool_dynamic_static.h" -#include "servers/audio_server.h" -#include "servers/visual/visual_server_raster.h" -#include "thread_uwp.h" -//#include "servers/visual/visual_server_wrap_mt.h" -#include "drivers/unix/ip_unix.h" #include "global_config.h" #include "io/marshalls.h" -#include "os/memory_pool_dynamic_prealloc.h" +#include "main/main.h" #include "platform/windows/packet_peer_udp_winsock.h" #include "platform/windows/stream_peer_winsock.h" #include "platform/windows/tcp_server_winsock.h" +#include "servers/audio_server.h" +#include "servers/visual/visual_server_raster.h" +#include "thread_uwp.h" #include <ppltasks.h> #include <wrl.h> @@ -149,9 +147,6 @@ const char *OSUWP::get_audio_driver_name(int p_driver) const { return AudioDriverManager::get_driver(p_driver)->get_name(); } -static MemoryPoolStatic *mempool_static = NULL; -static MemoryPoolDynamic *mempool_dynamic = NULL; - void OSUWP::initialize_core() { last_button_state = 0; @@ -161,32 +156,19 @@ void OSUWP::initialize_core() { ThreadUWP::make_default(); SemaphoreWindows::make_default(); MutexWindows::make_default(); + RWLockWindows::make_default(); FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES); FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA); FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM); - //FileAccessBufferedFA<FileAccessWindows>::make_default(); DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_RESOURCES); DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_USERDATA); DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM); - //TCPServerWinsock::make_default(); - //StreamPeerWinsock::make_default(); - TCPServerWinsock::make_default(); StreamPeerWinsock::make_default(); PacketPeerUDPWinsock::make_default(); - mempool_static = new MemoryPoolStaticMalloc; -#if 1 - mempool_dynamic = memnew(MemoryPoolDynamicStatic); -#else -#define DYNPOOL_SIZE 4 * 1024 * 1024 - void *buffer = malloc(DYNPOOL_SIZE); - mempool_dynamic = memnew(MemoryPoolDynamicPrealloc(buffer, DYNPOOL_SIZE)); - -#endif - // We need to know how often the clock is updated if (!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second)) ticks_per_second = 1000; @@ -259,13 +241,18 @@ void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_aud set_video_mode(vm); gl_context->make_current(); - rasterizer = memnew(RasterizerGLES2); - visual_server = memnew(VisualServerRaster(rasterizer)); + RasterizerGLES3::register_config(); + RasterizerGLES3::make_current(); + + visual_server = memnew(VisualServerRaster); + // FIXME: Reimplement threaded rendering? Or remove? + /* if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); } + */ // physics_server = memnew(PhysicsServerSW); @@ -288,7 +275,7 @@ void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_aud ERR_PRINT("Initializing audio failed."); } - power_manager = memnew(PowerWinRT); + power_manager = memnew(PowerUWP); managed_object->update_clipboard(); @@ -381,14 +368,6 @@ void OSUWP::finalize() { if (gl_context) memdelete(gl_context); #endif - if (rasterizer) - memdelete(rasterizer); - - /* - if (debugger_connection_console) { - memdelete(debugger_connection_console); - } - */ memdelete(input); @@ -400,11 +379,8 @@ void OSUWP::finalize() { joypad = nullptr; } -void OSUWP::finalize_core() { - if (mempool_dynamic) - memdelete(mempool_dynamic); - delete mempool_static; +void OSUWP::finalize_core() { } void OSUWP::vprint(const char *p_format, va_list p_list, bool p_stderr) { @@ -880,15 +856,20 @@ String OSUWP::get_data_dir() const { return String(data_folder->Path->Data()).replace("\\", "/"); } -PowerState OSWinrt::get_power_state() { +bool OSUWP::check_feature_support(const String &p_feature) { + + return VisualServer::get_singleton()->has_os_feature(p_feature); +} + +PowerState OSUWP::get_power_state() { return power_manager->get_power_state(); } -int OSWinrt::get_power_seconds_left() { +int OSUWP::get_power_seconds_left() { return power_manager->get_power_seconds_left(); } -int OSWinrt::get_power_percent_left() { +int OSUWP::get_power_percent_left() { return power_manager->get_power_percent_left(); } diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index 88a1dddae3..7d9e681da1 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -38,7 +38,7 @@ #include "main/input_default.h" #include "os/input.h" #include "os/os.h" -#include "power_winrt.h" +#include "power_uwp.h" #include "servers/audio_server.h" #include "servers/physics/physics_server_sw.h" #include "servers/physics_2d/physics_2d_server_sw.h" @@ -94,7 +94,6 @@ private: int old_x, old_y; Point2i center; VisualServer *visual_server; - Rasterizer *rasterizer; PhysicsServer *physics_server; Physics2DServer *physics_2d_server; int pressrc; @@ -107,7 +106,7 @@ private: AudioDriverXAudio2 audio_driver; - PowerWinRT *power_manager; + PowerUWP *power_manager; MouseMode mouse_mode; bool alt_mem; @@ -237,6 +236,8 @@ public: virtual void move_window_to_foreground(); virtual String get_data_dir() const; + virtual bool check_feature_support(const String &p_feature); + void set_gl_context(ContextEGL *p_context); void screen_size_changed(); diff --git a/platform/uwp/power_uwp.cpp b/platform/uwp/power_uwp.cpp new file mode 100644 index 0000000000..a8f0f5ba6d --- /dev/null +++ b/platform/uwp/power_uwp.cpp @@ -0,0 +1,74 @@ +/*************************************************************************/ +/* power_uwp.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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 "power_uwp.h" + +PowerUWP::PowerUWP() + : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) { +} + +PowerUWP::~PowerUWP() { +} + +bool PowerUWP::UpdatePowerInfo() { + // TODO, WinRT: Battery info is available on at least one WinRT platform (Windows Phone 8). Implement UpdatePowerInfo as appropriate. */ + /* Notes from SDL: + - the Win32 function, GetSystemPowerStatus, is not available for use on WinRT + - Windows Phone 8 has a 'Battery' class, which is documented as available for C++ + - More info on WP8's Battery class can be found at http://msdn.microsoft.com/library/windowsphone/develop/jj207231 + */ + return false; +} + +PowerState PowerUWP::get_power_state() { + if (UpdatePowerInfo()) { + return power_state; + } else { + WARN_PRINT("Power management is not implemented on this platform, defaulting to POWERSTATE_UNKNOWN"); + return POWERSTATE_UNKNOWN; + } +} + +int PowerUWP::get_power_seconds_left() { + if (UpdatePowerInfo()) { + return nsecs_left; + } else { + WARN_PRINT("Power management is not implemented on this platform, defaulting to -1"); + return -1; + } +} + +int PowerUWP::get_power_percent_left() { + if (UpdatePowerInfo()) { + return percent_left; + } else { + WARN_PRINT("Power management is not implemented on this platform, defaulting to -1"); + return -1; + } +} diff --git a/platform/uwp/power_uwp.h b/platform/uwp/power_uwp.h new file mode 100644 index 0000000000..465473bc1d --- /dev/null +++ b/platform/uwp/power_uwp.h @@ -0,0 +1,55 @@ +/*************************************************************************/ +/* power_uwp.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PLATFORM_UWP_POWER_UWP_H_ +#define PLATFORM_UWP_POWER_UWP_H_ + +#include "os/dir_access.h" +#include "os/file_access.h" +#include "os/power.h" + +class PowerUWP { + +private: + int nsecs_left; + int percent_left; + PowerState power_state; + + bool UpdatePowerInfo(); + +public: + PowerUWP(); + virtual ~PowerUWP(); + + PowerState get_power_state(); + int get_power_seconds_left(); + int get_power_percent_left(); +}; + +#endif /* PLATFORM_UWP_POWER_UWP_H_ */ |