Browse Source

Implement HTML5 touch events

(cherry picked from commit 86f5ac3d749a6d46d029a7f48e4fb190d51643c4)
Leon Krause 8 years ago
parent
commit
b717d1dc4c
2 changed files with 104 additions and 211 deletions
  1. 103 201
      platform/javascript/os_javascript.cpp
  2. 1 10
      platform/javascript/os_javascript.h

+ 103 - 201
platform/javascript/os_javascript.cpp

@@ -234,6 +234,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_pos().x - ev.mouse_motion.x;
+		ev.mouse_motion.relative_y = _input->get_mouse_pos().y - ev.mouse_motion.y;
+
+		_input->set_mouse_pos(Point2(ev.mouse_motion.x, ev.mouse_motion.y));
+		ev.mouse_motion.speed_x = _input->get_mouse_speed().x;
+		ev.mouse_motion.speed_y = _input->get_mouse_speed().y;
+
+		_input->parse_input_event(ev);
+	}
+	return true;
+}
+
 static InputEvent _setup_key_event(const EmscriptenKeyboardEvent *emscripten_event) {
 
 	InputEvent ev;
@@ -394,23 +482,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)
 
@@ -650,196 +742,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.ID = last_id++;
-				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.ID = last_id++;
-					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.ID = last_id++;
-				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.ID = last_id++;
-				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.ID = last_id++;
-				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_pos(Point2(ev.mouse_motion.x, ev.mouse_motion.y));
-				ev.mouse_motion.speed_x = input->get_mouse_speed().x;
-				ev.mouse_motion.speed_y = input->get_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.ID = last_id++;
-				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.ID = last_id++;
-				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.ID = last_id++;
-					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.ID = last_id++;
-			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.ID = last_id++;
-					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);

+ 1 - 10
platform/javascript/os_javascript.h

@@ -48,15 +48,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;
+
 	unsigned int last_id;
 	GFXInitFunc gfx_init_func;
 	void *gfx_init_ud;
@@ -166,7 +158,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);