Jelajahi Sumber

Implement mouse capture and hiding in HTML5 export

MOUSE_MODE_CONFINED cannot be implemented.
L. Krause 8 tahun lalu
induk
melakukan
101c542b77
2 mengubah file dengan 54 tambahan dan 10 penghapusan
  1. 49 7
      platform/javascript/os_javascript.cpp
  2. 5 3
      platform/javascript/os_javascript.h

+ 49 - 7
platform/javascript/os_javascript.cpp

@@ -513,20 +513,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 {

+ 5 - 3
platform/javascript/os_javascript.h

@@ -81,6 +81,9 @@ class OS_JavaScript : public OS_Unix {
 
 	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;
@@ -110,9 +113,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);