diff options
author | L. Krause <eska@eska.me> | 2017-04-24 21:41:39 +0200 |
---|---|---|
committer | L. Krause <eska@eska.me> | 2017-04-26 16:30:22 +0200 |
commit | 86f5ac3d749a6d46d029a7f48e4fb190d51643c4 (patch) | |
tree | 5faa48b716ee36309c138a83a546feeb311fb8a8 | |
parent | a99b6b2063c9259ef09bd1cc1289087460575d68 (diff) |
Implement HTML5 touch events
-rw-r--r-- | platform/javascript/os_javascript.cpp | 306 | ||||
-rw-r--r-- | platform/javascript/os_javascript.h | 11 |
2 files changed, 110 insertions, 207 deletions
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 45e77bc288..7d073654ce 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -41,9 +41,9 @@ #include <emscripten.h> #include <stdlib.h> -#define DOM_BUTTON_LEFT 0 -#define DOM_BUTTON_MIDDLE 1 -#define DOM_BUTTON_RIGHT 2 +#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) { @@ -145,7 +145,7 @@ static EM_BOOL _fullscreen_change_callback(int event_type, const EmscriptenFulls return false; } -static InputDefault* _input; +static InputDefault *_input; static EM_BOOL _mousebutton_callback(int event_type, const EmscriptenMouseEvent *mouse_event, void *user_data) { @@ -159,9 +159,9 @@ static EM_BOOL _mousebutton_callback(int event_type, const EmscriptenMouseEvent 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_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; + case DOM_BUTTON_RIGHT: ev.mouse_button.button_index = BUTTON_RIGHT; break; default: return false; } @@ -233,6 +233,94 @@ static EM_BOOL _wheel_callback(int event_type, const EmscriptenWheelEvent *wheel 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; @@ -364,23 +452,27 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i #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(mousemove, _mousemove_callback) - SET_EM_CALLBACK(mousedown, _mousebutton_callback) - SET_EM_CALLBACK(mouseup, _mousebutton_callback) - SET_EM_CALLBACK(wheel, _wheel_callback) - 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("#canvas", keydown, _keydown_callback) + SET_EM_CALLBACK("#canvas", keypress, _keypress_callback) + SET_EM_CALLBACK("#canvas", 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) @@ -623,186 +715,6 @@ void OS_JavaScript::main_loop_focusin() { //audio_driver_javascript.set_pause(false); } -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); diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index 5d86640d95..0c956ecba6 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -49,15 +49,7 @@ 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; + GFXInitFunc gfx_init_func; void *gfx_init_ud; @@ -165,7 +157,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); |