浏览代码

Merge pull request #71045 from reduz/use-bitfield-in-core-types

Use BitField<> in core type masks
Rémi Verschelde 2 年之前
父节点
当前提交
e7905f4f48
共有 69 个文件被更改,包括 494 次插入446 次删除
  1. 88 59
      core/core_constants.cpp
  2. 1 0
      core/core_constants.h
  3. 2 0
      core/extension/extension_api_dump.cpp
  4. 15 10
      core/input/input.cpp
  5. 3 3
      core/input/input.h
  6. 9 50
      core/input/input_enums.h
  7. 32 35
      core/input/input_event.cpp
  8. 4 4
      core/input/input_event.h
  9. 1 1
      core/object/method_bind.h
  10. 35 4
      core/variant/binder_common.h
  11. 6 3
      core/variant/type_info.h
  12. 54 54
      doc/classes/@GlobalScope.xml
  13. 1 1
      doc/classes/BaseButton.xml
  14. 1 1
      doc/classes/DisplayServer.xml
  15. 1 1
      doc/classes/Input.xml
  16. 1 1
      doc/classes/InputEventMouse.xml
  17. 2 2
      editor/animation_track_editor.cpp
  18. 1 1
      editor/debugger/editor_profiler.cpp
  19. 1 1
      editor/debugger/editor_visual_profiler.cpp
  20. 1 0
      editor/doc_tools.cpp
  21. 1 1
      editor/editor_inspector.cpp
  22. 1 1
      editor/editor_properties.cpp
  23. 1 1
      editor/editor_title_bar.cpp
  24. 1 1
      editor/import/scene_import_settings.cpp
  25. 1 1
      editor/plugins/abstract_polygon_2d_editor.cpp
  26. 1 1
      editor/plugins/animation_blend_space_1d_editor.cpp
  27. 1 1
      editor/plugins/animation_blend_space_2d_editor.cpp
  28. 1 1
      editor/plugins/animation_state_machine_editor.cpp
  29. 1 1
      editor/plugins/canvas_item_editor_plugin.cpp
  30. 1 1
      editor/plugins/material_editor_plugin.cpp
  31. 1 1
      editor/plugins/mesh_editor_plugin.cpp
  32. 5 5
      editor/plugins/node_3d_editor_plugin.cpp
  33. 1 1
      editor/plugins/polygon_3d_editor_plugin.cpp
  34. 2 2
      editor/plugins/sprite_frames_editor_plugin.cpp
  35. 1 1
      editor/plugins/texture_layered_editor_plugin.cpp
  36. 20 20
      platform/android/android_input_handler.cpp
  37. 6 6
      platform/android/android_input_handler.h
  38. 2 2
      platform/android/display_server_android.cpp
  39. 1 1
      platform/android/display_server_android.h
  40. 5 5
      platform/android/java_godot_lib_jni.cpp
  41. 15 9
      platform/linuxbsd/joypad_linux.cpp
  42. 1 1
      platform/linuxbsd/joypad_linux.h
  43. 7 7
      platform/linuxbsd/x11/display_server_x11.cpp
  44. 3 3
      platform/linuxbsd/x11/display_server_x11.h
  45. 3 3
      platform/macos/display_server_macos.h
  46. 2 2
      platform/macos/display_server_macos.mm
  47. 1 1
      platform/macos/godot_content_view.h
  48. 22 19
      platform/macos/godot_content_view.mm
  49. 15 12
      platform/macos/joypad_macos.cpp
  50. 12 10
      platform/web/display_server_web.cpp
  51. 4 4
      platform/windows/display_server_windows.cpp
  52. 2 2
      platform/windows/display_server_windows.h
  53. 15 10
      platform/windows/joypad_windows.cpp
  54. 3 3
      scene/gui/base_button.cpp
  55. 3 3
      scene/gui/base_button.h
  56. 2 2
      scene/gui/code_edit.cpp
  57. 1 1
      scene/gui/line_edit.cpp
  58. 2 2
      scene/gui/popup_menu.cpp
  59. 1 1
      scene/gui/popup_menu.h
  60. 1 1
      scene/gui/spin_box.cpp
  61. 1 1
      scene/gui/text_edit.cpp
  62. 1 1
      scene/gui/view_panner.cpp
  63. 19 18
      scene/main/viewport.cpp
  64. 2 2
      scene/main/viewport.h
  65. 2 2
      servers/display_server.cpp
  66. 1 1
      servers/display_server.h
  67. 4 4
      tests/scene/test_code_edit.h
  68. 29 29
      tests/scene/test_text_edit.h
  69. 7 7
      tests/test_macros.h

+ 88 - 59
core/core_constants.cpp

@@ -39,6 +39,7 @@ struct _CoreConstant {
 #ifdef DEBUG_METHODS_ENABLED
 	StringName enum_name;
 	bool ignore_value_in_docs = false;
+	bool is_bitfield = false;
 #endif
 	const char *name = nullptr;
 	int64_t value = 0;
@@ -46,9 +47,10 @@ struct _CoreConstant {
 	_CoreConstant() {}
 
 #ifdef DEBUG_METHODS_ENABLED
-	_CoreConstant(const StringName &p_enum_name, const char *p_name, int64_t p_value, bool p_ignore_value_in_docs = false) :
+	_CoreConstant(const StringName &p_enum_name, const char *p_name, int64_t p_value, bool p_ignore_value_in_docs = false, bool p_is_bitfield = false) :
 			enum_name(p_enum_name),
 			ignore_value_in_docs(p_ignore_value_in_docs),
+			is_bitfield(p_is_bitfield),
 			name(p_name),
 			value(p_value) {
 	}
@@ -70,13 +72,22 @@ static Vector<_CoreConstant> _global_constants;
 #define BIND_CORE_ENUM_CONSTANT(m_constant) \
 	_global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant));
 
+#define BIND_CORE_BITFIELD_FLAG(m_constant) \
+	_global_constants.push_back(_CoreConstant(__constant_get_bitfield_name(m_constant, #m_constant), #m_constant, m_constant, false, true));
+
 // This just binds enum classes as if they were regular enum constants.
 #define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
 	_global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member), #m_prefix "_" #m_member, (int64_t)m_enum::m_member));
 
+#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
+	_global_constants.push_back(_CoreConstant(__constant_get_bitfield_name(m_enum::m_member, #m_prefix "_" #m_member), #m_prefix "_" #m_member, (int64_t)m_enum::m_member, false, true));
+
 #define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
 	_global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_enum::m_member, #m_name), #m_name, (int64_t)m_enum::m_member));
 
+#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
+	_global_constants.push_back(_CoreConstant(__constant_get_bitfield_name(m_enum::m_member, #m_name), #m_name, (int64_t)m_enum::m_member, false, true));
+
 #define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
 	_global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member), #m_prefix "_" #m_member, (int64_t)m_enum::m_member, true));
 
@@ -100,13 +111,22 @@ static Vector<_CoreConstant> _global_constants;
 #define BIND_CORE_ENUM_CONSTANT(m_constant) \
 	_global_constants.push_back(_CoreConstant(#m_constant, m_constant));
 
+#define BIND_CORE_BITFIELD_FLAG(m_constant) \
+	_global_constants.push_back(_CoreConstant(#m_constant, m_constant));
+
 // This just binds enum classes as if they were regular enum constants.
 #define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
 	_global_constants.push_back(_CoreConstant(#m_prefix "_" #m_member, (int64_t)m_enum::m_member));
 
+#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
+	_global_constants.push_back(_CoreConstant(#m_prefix "_" #m_member, (int64_t)m_enum::m_member));
+
 #define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
 	_global_constants.push_back(_CoreConstant(#m_name, (int64_t)m_enum::m_member));
 
+#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
+	_global_constants.push_back(_CoreConstant(#m_name, (int64_t)m_enum::m_member));
+
 #define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
 	_global_constants.push_back(_CoreConstant(#m_prefix "_" #m_member, (int64_t)m_enum::m_member));
 
@@ -439,15 +459,15 @@ void register_global_constants() {
 	BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DIVISION);
 	BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, YDIAERESIS);
 
-	BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(KeyModifierMask, KEY_CODE_MASK, CODE_MASK);
-	BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(KeyModifierMask, KEY_MODIFIER_MASK, MODIFIER_MASK);
-	BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, CMD_OR_CTRL);
-	BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, SHIFT);
-	BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, ALT);
-	BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, META);
-	BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, CTRL);
-	BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, KPAD);
-	BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, GROUP_SWITCH);
+	BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(KeyModifierMask, KEY_CODE_MASK, CODE_MASK);
+	BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(KeyModifierMask, KEY_MODIFIER_MASK, MODIFIER_MASK);
+	BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, CMD_OR_CTRL);
+	BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, SHIFT);
+	BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, ALT);
+	BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, META);
+	BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, CTRL);
+	BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, KPAD);
+	BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, GROUP_SWITCH);
 
 	BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, NONE);
 	BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, LEFT);
@@ -459,11 +479,12 @@ void register_global_constants() {
 	BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_RIGHT);
 	BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(MouseButton, MOUSE_BUTTON_XBUTTON1, MB_XBUTTON1);
 	BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(MouseButton, MOUSE_BUTTON_XBUTTON2, MB_XBUTTON2);
-	BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_LEFT);
-	BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_RIGHT);
-	BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_MIDDLE);
-	BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_XBUTTON1);
-	BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_XBUTTON2);
+
+	BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, LEFT);
+	BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, RIGHT);
+	BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, MIDDLE);
+	BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, MB_XBUTTON1);
+	BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, MB_XBUTTON2);
 
 	BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, INVALID);
 	BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, A);
@@ -622,50 +643,50 @@ void register_global_constants() {
 	BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PASSWORD);
 	BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX);
 
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_STORAGE);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR);
-
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CHECKABLE);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CHECKED);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_INTERNATIONALIZED);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_GROUP);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CATEGORY);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SUBGROUP);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CLASS_IS_BITFIELD);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NO_INSTANCE_STATE);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_RESTART_IF_CHANGED);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_VARIABLE);
-
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_STORE_IF_NULL);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CLASS_IS_ENUM);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NIL_IS_VARIANT);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_INTERNAL);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_HIGH_END_GFX);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_KEYING_INCREMENTS);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFERRED_SET_RESOURCE);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR_BASIC_SETTING);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_READ_ONLY);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_ARRAY);
-
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT_INTL);
-	BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NO_EDITOR);
-
-	BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_NORMAL);
-	BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_EDITOR);
-	BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_CONST);
-	BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VIRTUAL);
-	BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VARARG);
-	BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_STATIC);
-	BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_OBJECT_CORE);
-	BIND_CORE_ENUM_CONSTANT(METHOD_FLAGS_DEFAULT);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NONE);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_STORAGE);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_EDITOR);
+
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CHECKABLE);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CHECKED);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_INTERNATIONALIZED);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_GROUP);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CATEGORY);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_SUBGROUP);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CLASS_IS_BITFIELD);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NO_INSTANCE_STATE);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_RESTART_IF_CHANGED);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_SCRIPT_VARIABLE);
+
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_STORE_IF_NULL);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CLASS_IS_ENUM);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NIL_IS_VARIANT);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_INTERNAL);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_HIGH_END_GFX);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_KEYING_INCREMENTS);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_DEFERRED_SET_RESOURCE);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_EDITOR_BASIC_SETTING);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_READ_ONLY);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_ARRAY);
+
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_DEFAULT);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_DEFAULT_INTL);
+	BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NO_EDITOR);
+
+	BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_NORMAL);
+	BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_EDITOR);
+	BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_CONST);
+	BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_VIRTUAL);
+	BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_VARARG);
+	BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_STATIC);
+	BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_OBJECT_CORE);
+	BIND_CORE_BITFIELD_FLAG(METHOD_FLAGS_DEFAULT);
 
 	BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL);
 	BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BOOL", Variant::BOOL);
@@ -753,6 +774,10 @@ StringName CoreConstants::get_global_constant_enum(int p_idx) {
 	return _global_constants[p_idx].enum_name;
 }
 
+bool CoreConstants::is_global_constant_bitfield(int p_idx) {
+	return _global_constants[p_idx].is_bitfield;
+}
+
 bool CoreConstants::get_ignore_value_in_docs(int p_idx) {
 	return _global_constants[p_idx].ignore_value_in_docs;
 }
@@ -761,6 +786,10 @@ StringName CoreConstants::get_global_constant_enum(int p_idx) {
 	return StringName();
 }
 
+bool CoreConstants::is_global_constant_bitfield(int p_idx) {
+	return false;
+}
+
 bool CoreConstants::get_ignore_value_in_docs(int p_idx) {
 	return false;
 }

+ 1 - 0
core/core_constants.h

@@ -37,6 +37,7 @@ class CoreConstants {
 public:
 	static int get_global_constant_count();
 	static StringName get_global_constant_enum(int p_idx);
+	static bool is_global_constant_bitfield(int p_idx);
 	static bool get_ignore_value_in_docs(int p_idx);
 	static const char *get_global_constant_name(int p_idx);
 	static int64_t get_global_constant_value(int p_idx);

+ 2 - 0
core/extension/extension_api_dump.cpp

@@ -463,12 +463,14 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 			int64_t value = CoreConstants::get_global_constant_value(i);
 			String enum_name = CoreConstants::get_global_constant_enum(i);
 			String name = CoreConstants::get_global_constant_name(i);
+			bool bitfield = CoreConstants::is_global_constant_bitfield(i);
 			if (!enum_name.is_empty()) {
 				enum_list[enum_name].push_back(Pair<String, int64_t>(name, value));
 			} else {
 				Dictionary d;
 				d["name"] = name;
 				d["value"] = value;
+				d["is_bitfield"] = bitfield;
 				constants.push_back(d);
 			}
 		}

+ 15 - 10
core/input/input.cpp

@@ -237,7 +237,7 @@ bool Input::is_anything_pressed() const {
 	}
 	return !keys_pressed.is_empty() ||
 			!joy_buttons_pressed.is_empty() ||
-			mouse_button_mask > MouseButton::NONE;
+			!mouse_button_mask.is_empty();
 }
 
 bool Input::is_key_pressed(Key p_keycode) const {
@@ -252,7 +252,7 @@ bool Input::is_physical_key_pressed(Key p_keycode) const {
 
 bool Input::is_mouse_button_pressed(MouseButton p_button) const {
 	_THREAD_SAFE_METHOD_
-	return (mouse_button_mask & mouse_button_to_mask(p_button)) != MouseButton::NONE;
+	return mouse_button_mask.has_flag(mouse_button_to_mask(p_button));
 }
 
 static JoyAxis _combine_device(JoyAxis p_value, int p_device) {
@@ -504,9 +504,9 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
 
 	if (mb.is_valid()) {
 		if (mb->is_pressed()) {
-			mouse_button_mask |= mouse_button_to_mask(mb->get_button_index());
+			mouse_button_mask.set_flag(mouse_button_to_mask(mb->get_button_index()));
 		} else {
-			mouse_button_mask &= ~mouse_button_to_mask(mb->get_button_index());
+			mouse_button_mask.clear_flag(mouse_button_to_mask(mb->get_button_index()));
 		}
 
 		Point2 pos = mb->get_global_position();
@@ -534,7 +534,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
 		Vector2 relative = mm->get_relative();
 		mouse_velocity_track.update(relative);
 
-		if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && (mm->get_button_mask() & MouseButton::LEFT) != MouseButton::NONE) {
+		if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && mm->get_button_mask().has_flag(MouseButtonMask::LEFT)) {
 			Ref<InputEventScreenDrag> drag_event;
 			drag_event.instantiate();
 
@@ -585,11 +585,14 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
 				button_event->set_pressed(st->is_pressed());
 				button_event->set_button_index(MouseButton::LEFT);
 				button_event->set_double_click(st->is_double_tap());
+
+				BitField<MouseButtonMask> ev_bm = mouse_button_mask;
 				if (st->is_pressed()) {
-					button_event->set_button_mask(MouseButton(mouse_button_mask | MouseButton::MASK_LEFT));
+					ev_bm.set_flag(MouseButtonMask::LEFT);
 				} else {
-					button_event->set_button_mask(MouseButton(mouse_button_mask & ~MouseButton::MASK_LEFT));
+					ev_bm.clear_flag(MouseButtonMask::LEFT);
 				}
+				button_event->set_button_mask(ev_bm);
 
 				_parse_input_event_impl(button_event, true);
 			}
@@ -740,7 +743,7 @@ Point2 Input::get_last_mouse_velocity() {
 	return mouse_velocity_track.velocity;
 }
 
-MouseButton Input::get_mouse_button_mask() const {
+BitField<MouseButtonMask> Input::get_mouse_button_mask() const {
 	return mouse_button_mask; // do not trust OS implementation, should remove it - OS::get_singleton()->get_mouse_button_state();
 }
 
@@ -821,7 +824,9 @@ void Input::ensure_touch_mouse_raised() {
 		button_event->set_global_position(mouse_pos);
 		button_event->set_pressed(false);
 		button_event->set_button_index(MouseButton::LEFT);
-		button_event->set_button_mask(MouseButton(mouse_button_mask & ~MouseButton::MASK_LEFT));
+		BitField<MouseButtonMask> ev_bm = mouse_button_mask;
+		ev_bm.clear_flag(MouseButtonMask::LEFT);
+		button_event->set_button_mask(ev_bm);
 
 		_parse_input_event_impl(button_event, true);
 	}
@@ -1022,7 +1027,7 @@ void Input::joy_axis(int p_device, JoyAxis p_axis, float p_value) {
 	}
 }
 
-void Input::joy_hat(int p_device, HatMask p_val) {
+void Input::joy_hat(int p_device, BitField<HatMask> p_val) {
 	_THREAD_SAFE_METHOD_;
 	const Joypad &joy = joy_names[p_device];
 

+ 3 - 3
core/input/input.h

@@ -82,7 +82,7 @@ public:
 	typedef void (*EventDispatchFunc)(const Ref<InputEvent> &p_event);
 
 private:
-	MouseButton mouse_button_mask = MouseButton::NONE;
+	BitField<MouseButtonMask> mouse_button_mask;
 
 	RBSet<Key> physical_keys_pressed;
 	RBSet<Key> keys_pressed;
@@ -273,7 +273,7 @@ public:
 
 	Point2 get_mouse_position() const;
 	Vector2 get_last_mouse_velocity();
-	MouseButton get_mouse_button_mask() const;
+	BitField<MouseButtonMask> get_mouse_button_mask() const;
 
 	void warp_mouse(const Vector2 &p_position);
 	Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect);
@@ -310,7 +310,7 @@ public:
 	void parse_mapping(String p_mapping);
 	void joy_button(int p_device, JoyButton p_button, bool p_pressed);
 	void joy_axis(int p_device, JoyAxis p_axis, float p_value);
-	void joy_hat(int p_device, HatMask p_val);
+	void joy_hat(int p_device, BitField<HatMask> p_val);
 
 	void add_joy_mapping(String p_mapping, bool p_update_existing = false);
 	void remove_joy_mapping(String p_guid);

+ 9 - 50
core/input/input_enums.h

@@ -119,59 +119,18 @@ enum class MouseButton {
 	WHEEL_RIGHT = 7,
 	MB_XBUTTON1 = 8, // "XBUTTON1" is a reserved word on Windows.
 	MB_XBUTTON2 = 9, // "XBUTTON2" is a reserved word on Windows.
-	MASK_LEFT = (1 << (LEFT - 1)),
-	MASK_RIGHT = (1 << (RIGHT - 1)),
-	MASK_MIDDLE = (1 << (MIDDLE - 1)),
-	MASK_XBUTTON1 = (1 << (MB_XBUTTON1 - 1)),
-	MASK_XBUTTON2 = (1 << (MB_XBUTTON2 - 1)),
 };
 
-inline MouseButton mouse_button_to_mask(MouseButton button) {
-	return MouseButton(1 << ((int)button - 1));
-}
-
-inline MouseButton operator&(MouseButton a, MouseButton b) {
-	return (MouseButton)((int)a & (int)b);
-}
-
-inline MouseButton operator|(MouseButton a, MouseButton b) {
-	return (MouseButton)((int)a | (int)b);
-}
-
-inline MouseButton operator^(MouseButton a, MouseButton b) {
-	return (MouseButton)((int)a ^ (int)b);
-}
-
-inline MouseButton &operator|=(MouseButton &a, MouseButton b) {
-	return (MouseButton &)((int &)a |= (int)b);
-}
-
-inline MouseButton &operator&=(MouseButton &a, MouseButton b) {
-	return (MouseButton &)((int &)a &= (int)b);
-}
-
-inline MouseButton operator~(MouseButton a) {
-	return (MouseButton)(~(int)a);
-}
-
-inline HatMask operator|(HatMask a, HatMask b) {
-	return (HatMask)((int)a | (int)b);
-}
-
-inline HatMask operator&(HatMask a, HatMask b) {
-	return (HatMask)((int)a & (int)b);
-}
-
-inline HatMask &operator&=(HatMask &a, HatMask b) {
-	return (HatMask &)((int &)a &= (int)b);
-}
-
-inline HatMask &operator|=(HatMask &a, HatMask b) {
-	return (HatMask &)((int &)a |= (int)b);
-}
+enum class MouseButtonMask {
+	LEFT = (1 << (int(MouseButton::LEFT) - 1)),
+	RIGHT = (1 << (int(MouseButton::RIGHT) - 1)),
+	MIDDLE = (1 << (int(MouseButton::MIDDLE) - 1)),
+	MB_XBUTTON1 = (1 << (int(MouseButton::MB_XBUTTON1) - 1)),
+	MB_XBUTTON2 = (1 << (int(MouseButton::MB_XBUTTON2) - 1)),
+};
 
-inline HatMask operator~(HatMask a) {
-	return (HatMask)(~(int)a);
+inline MouseButtonMask mouse_button_to_mask(MouseButton button) {
+	return MouseButtonMask(1 << ((int)button - 1));
 }
 
 #endif // INPUT_ENUMS_H

+ 32 - 35
core/input/input_event.cpp

@@ -216,25 +216,25 @@ void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModif
 	set_meta_pressed(event->is_meta_pressed());
 }
 
-Key InputEventWithModifiers::get_modifiers_mask() const {
-	Key mask = Key::NONE;
+BitField<KeyModifierMask> InputEventWithModifiers::get_modifiers_mask() const {
+	BitField<KeyModifierMask> mask;
 	if (is_ctrl_pressed()) {
-		mask |= KeyModifierMask::CTRL;
+		mask.set_flag(KeyModifierMask::CTRL);
 	}
 	if (is_shift_pressed()) {
-		mask |= KeyModifierMask::SHIFT;
+		mask.set_flag(KeyModifierMask::SHIFT);
 	}
 	if (is_alt_pressed()) {
-		mask |= KeyModifierMask::ALT;
+		mask.set_flag(KeyModifierMask::ALT);
 	}
 	if (is_meta_pressed()) {
-		mask |= KeyModifierMask::META;
+		mask.set_flag(KeyModifierMask::META);
 	}
 	if (is_command_or_control_autoremap()) {
 #ifdef MACOS_ENABLED
-		mask |= KeyModifierMask::META;
+		mask.set_flag(KeyModifierMask::META);
 #else
-		mask |= KeyModifierMask::CTRL;
+		mask.set_flag(KeyModifierMask::CTRL);
 #endif
 	}
 	return mask;
@@ -356,11 +356,11 @@ bool InputEventKey::is_echo() const {
 }
 
 Key InputEventKey::get_keycode_with_modifiers() const {
-	return keycode | get_modifiers_mask();
+	return keycode | (int64_t)get_modifiers_mask();
 }
 
 Key InputEventKey::get_physical_keycode_with_modifiers() const {
-	return physical_keycode | get_modifiers_mask();
+	return physical_keycode | (int64_t)get_modifiers_mask();
 }
 
 String InputEventKey::as_text() const {
@@ -440,8 +440,8 @@ bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool p_exact_ma
 	} else {
 		match = get_physical_keycode() == key->get_physical_keycode();
 	}
-	Key action_mask = get_modifiers_mask();
-	Key key_mask = key->get_modifiers_mask();
+	Key action_mask = (Key)(int64_t)get_modifiers_mask();
+	Key key_mask = (Key)(int64_t)key->get_modifiers_mask();
 	if (key->is_pressed()) {
 		match &= (action_mask & key_mask) == action_mask;
 	}
@@ -505,12 +505,12 @@ void InputEventKey::_bind_methods() {
 
 ///////////////////////////////////
 
-void InputEventMouse::set_button_mask(MouseButton p_mask) {
+void InputEventMouse::set_button_mask(BitField<MouseButtonMask> p_mask) {
 	button_mask = p_mask;
 	emit_changed();
 }
 
-MouseButton InputEventMouse::get_button_mask() const {
+BitField<MouseButtonMask> InputEventMouse::get_button_mask() const {
 	return button_mask;
 }
 
@@ -610,8 +610,8 @@ bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool p_
 	}
 
 	bool match = button_index == mb->button_index;
-	Key action_modifiers_mask = get_modifiers_mask();
-	Key button_modifiers_mask = mb->get_modifiers_mask();
+	Key action_modifiers_mask = (Key)(int64_t)get_modifiers_mask();
+	Key button_modifiers_mask = (Key)(int64_t)mb->get_modifiers_mask();
 	if (mb->is_pressed()) {
 		match &= (action_modifiers_mask & button_modifiers_mask) == action_modifiers_mask;
 	}
@@ -808,26 +808,23 @@ String InputEventMouseMotion::as_text() const {
 }
 
 String InputEventMouseMotion::to_string() {
-	MouseButton mouse_button_mask = get_button_mask();
+	BitField<MouseButtonMask> mouse_button_mask = get_button_mask();
 	String button_mask_string = itos((int64_t)mouse_button_mask);
-	switch (mouse_button_mask) {
-		case MouseButton::MASK_LEFT:
-			button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::LEFT - 1]));
-			break;
-		case MouseButton::MASK_MIDDLE:
-			button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MIDDLE - 1]));
-			break;
-		case MouseButton::MASK_RIGHT:
-			button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::RIGHT - 1]));
-			break;
-		case MouseButton::MASK_XBUTTON1:
-			button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON1 - 1]));
-			break;
-		case MouseButton::MASK_XBUTTON2:
-			button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON2 - 1]));
-			break;
-		default:
-			break;
+
+	if (mouse_button_mask.has_flag(MouseButtonMask::LEFT)) {
+		button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::LEFT - 1]));
+	}
+	if (mouse_button_mask.has_flag(MouseButtonMask::MIDDLE)) {
+		button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MIDDLE - 1]));
+	}
+	if (mouse_button_mask.has_flag(MouseButtonMask::RIGHT)) {
+		button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::RIGHT - 1]));
+	}
+	if (mouse_button_mask.has_flag(MouseButtonMask::MB_XBUTTON1)) {
+		button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON1 - 1]));
+	}
+	if (mouse_button_mask.has_flag(MouseButtonMask::MB_XBUTTON2)) {
+		button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON2 - 1]));
 	}
 
 	// Work around the fact vformat can only take 5 substitutions but 7 need to be passed.

+ 4 - 4
core/input/input_event.h

@@ -138,7 +138,7 @@ public:
 
 	void set_modifiers_from_event(const InputEventWithModifiers *event);
 
-	Key get_modifiers_mask() const;
+	BitField<KeyModifierMask> get_modifiers_mask() const;
 
 	virtual String as_text() const override;
 	virtual String to_string() override;
@@ -195,7 +195,7 @@ public:
 class InputEventMouse : public InputEventWithModifiers {
 	GDCLASS(InputEventMouse, InputEventWithModifiers);
 
-	MouseButton button_mask = MouseButton::NONE;
+	BitField<MouseButtonMask> button_mask;
 
 	Vector2 pos;
 	Vector2 global_pos;
@@ -204,8 +204,8 @@ protected:
 	static void _bind_methods();
 
 public:
-	void set_button_mask(MouseButton p_mask);
-	MouseButton get_button_mask() const;
+	void set_button_mask(BitField<MouseButtonMask> p_mask);
+	BitField<MouseButtonMask> get_button_mask() const;
 
 	void set_position(const Vector2 &p_pos);
 	Vector2 get_position() const;

+ 1 - 1
core/object/method_bind.h

@@ -33,7 +33,7 @@
 
 #include "core/variant/binder_common.h"
 
-VARIANT_ENUM_CAST(MethodFlags)
+VARIANT_BITFIELD_CAST(MethodFlags)
 
 // some helpers
 

+ 35 - 4
core/variant/binder_common.h

@@ -146,22 +146,53 @@ VARIANT_ENUM_CAST(Side);
 VARIANT_ENUM_CAST(ClockDirection);
 VARIANT_ENUM_CAST(Corner);
 VARIANT_ENUM_CAST(HatDir);
-VARIANT_ENUM_CAST(HatMask);
+VARIANT_BITFIELD_CAST(HatMask);
 VARIANT_ENUM_CAST(JoyAxis);
 VARIANT_ENUM_CAST(JoyButton);
-VARIANT_ENUM_CAST(Key);
-VARIANT_ENUM_CAST(KeyModifierMask);
+
 VARIANT_ENUM_CAST(MIDIMessage);
 VARIANT_ENUM_CAST(MouseButton);
+VARIANT_BITFIELD_CAST(MouseButtonMask);
 VARIANT_ENUM_CAST(Orientation);
 VARIANT_ENUM_CAST(HorizontalAlignment);
 VARIANT_ENUM_CAST(VerticalAlignment);
 VARIANT_ENUM_CAST(InlineAlignment);
 VARIANT_ENUM_CAST(PropertyHint);
-VARIANT_ENUM_CAST(PropertyUsageFlags);
+VARIANT_BITFIELD_CAST(PropertyUsageFlags);
 VARIANT_ENUM_CAST(Variant::Type);
 VARIANT_ENUM_CAST(Variant::Operator);
 
+// Key
+
+VARIANT_ENUM_CAST(Key);
+VARIANT_BITFIELD_CAST(KeyModifierMask);
+
+static inline Key &operator|=(Key &a, BitField<KeyModifierMask> b) {
+	a = static_cast<Key>(static_cast<int>(a) | static_cast<int>(b.operator int64_t()));
+	return a;
+}
+
+static inline Key &operator&=(Key &a, BitField<KeyModifierMask> b) {
+	a = static_cast<Key>(static_cast<int>(a) & static_cast<int>(b.operator int64_t()));
+	return a;
+}
+
+static inline Key operator|(Key a, BitField<KeyModifierMask> b) {
+	return (Key)((int)a | (int)b.operator int64_t());
+}
+
+static inline Key operator&(Key a, BitField<KeyModifierMask> b) {
+	return (Key)((int)a & (int)b.operator int64_t());
+}
+
+static inline Key operator+(BitField<KeyModifierMask> a, Key b) {
+	return (Key)((int)a.operator int64_t() + (int)b);
+}
+
+static inline Key operator|(BitField<KeyModifierMask> a, Key b) {
+	return (Key)((int)a.operator int64_t() | (int)b);
+}
+
 template <>
 struct VariantCaster<char32_t> {
 	static _FORCE_INLINE_ char32_t cast(const Variant &p_variant) {

+ 6 - 3
core/variant/type_info.h

@@ -287,11 +287,14 @@ class BitField {
 	int64_t value = 0;
 
 public:
-	_FORCE_INLINE_ void set_flag(T p_flag) { value |= p_flag; }
-	_FORCE_INLINE_ bool has_flag(T p_flag) const { return value & p_flag; }
-	_FORCE_INLINE_ void clear_flag(T p_flag) { return value &= ~p_flag; }
+	_FORCE_INLINE_ void set_flag(T p_flag) { value |= (int64_t)p_flag; }
+	_FORCE_INLINE_ bool has_flag(T p_flag) const { return value & (int64_t)p_flag; }
+	_FORCE_INLINE_ bool is_empty() const { return value == 0; }
+	_FORCE_INLINE_ void clear_flag(T p_flag) { value &= ~(int64_t)p_flag; }
+	_FORCE_INLINE_ void clear() { value = 0; }
 	_FORCE_INLINE_ BitField() = default;
 	_FORCE_INLINE_ BitField(int64_t p_value) { value = p_value; }
+	_FORCE_INLINE_ BitField(T p_value) { value = (int64_t)p_value; }
 	_FORCE_INLINE_ operator int64_t() const { return value; }
 	_FORCE_INLINE_ operator Variant() const { return value; }
 };

+ 54 - 54
doc/classes/@GlobalScope.xml

@@ -2319,31 +2319,31 @@
 		<constant name="KEY_YDIAERESIS" value="255" enum="Key">
 			ÿ key.
 		</constant>
-		<constant name="KEY_CODE_MASK" value="8388607" enum="KeyModifierMask">
+		<constant name="KEY_CODE_MASK" value="8388607" enum="KeyModifierMask" is_bitfield="true">
 			Key Code mask.
 		</constant>
-		<constant name="KEY_MODIFIER_MASK" value="532676608" enum="KeyModifierMask">
+		<constant name="KEY_MODIFIER_MASK" value="532676608" enum="KeyModifierMask" is_bitfield="true">
 			Modifier key mask.
 		</constant>
-		<constant name="KEY_MASK_CMD_OR_CTRL" value="16777216" enum="KeyModifierMask">
+		<constant name="KEY_MASK_CMD_OR_CTRL" value="16777216" enum="KeyModifierMask" is_bitfield="true">
 			Automatically remapped to [constant KEY_META] on macOS and [constant KEY_CTRL] on other platforms, this mask is never set in the actual events, and should be used for key mapping only.
 		</constant>
-		<constant name="KEY_MASK_SHIFT" value="33554432" enum="KeyModifierMask">
+		<constant name="KEY_MASK_SHIFT" value="33554432" enum="KeyModifierMask" is_bitfield="true">
 			Shift key mask.
 		</constant>
-		<constant name="KEY_MASK_ALT" value="67108864" enum="KeyModifierMask">
+		<constant name="KEY_MASK_ALT" value="67108864" enum="KeyModifierMask" is_bitfield="true">
 			Alt or Option (on macOS) key mask.
 		</constant>
-		<constant name="KEY_MASK_META" value="134217728" enum="KeyModifierMask">
+		<constant name="KEY_MASK_META" value="134217728" enum="KeyModifierMask" is_bitfield="true">
 			Command (on macOS) or Meta/Windows key mask.
 		</constant>
-		<constant name="KEY_MASK_CTRL" value="268435456" enum="KeyModifierMask">
+		<constant name="KEY_MASK_CTRL" value="268435456" enum="KeyModifierMask" is_bitfield="true">
 			Ctrl key mask.
 		</constant>
-		<constant name="KEY_MASK_KPAD" value="536870912" enum="KeyModifierMask">
+		<constant name="KEY_MASK_KPAD" value="536870912" enum="KeyModifierMask" is_bitfield="true">
 			Keypad key mask.
 		</constant>
-		<constant name="KEY_MASK_GROUP_SWITCH" value="1073741824" enum="KeyModifierMask">
+		<constant name="KEY_MASK_GROUP_SWITCH" value="1073741824" enum="KeyModifierMask" is_bitfield="true">
 			Group Switch key mask.
 		</constant>
 		<constant name="MOUSE_BUTTON_NONE" value="0" enum="MouseButton">
@@ -2376,19 +2376,19 @@
 		<constant name="MOUSE_BUTTON_XBUTTON2" value="9" enum="MouseButton">
 			Extra mouse button 2. This is sometimes present, usually to the sides of the mouse.
 		</constant>
-		<constant name="MOUSE_BUTTON_MASK_LEFT" value="1" enum="MouseButton">
+		<constant name="MOUSE_BUTTON_MASK_LEFT" value="1" enum="MouseButtonMask" is_bitfield="true">
 			Primary mouse button mask, usually for the left button.
 		</constant>
-		<constant name="MOUSE_BUTTON_MASK_RIGHT" value="2" enum="MouseButton">
+		<constant name="MOUSE_BUTTON_MASK_RIGHT" value="2" enum="MouseButtonMask" is_bitfield="true">
 			Secondary mouse button mask, usually for the right button.
 		</constant>
-		<constant name="MOUSE_BUTTON_MASK_MIDDLE" value="4" enum="MouseButton">
+		<constant name="MOUSE_BUTTON_MASK_MIDDLE" value="4" enum="MouseButtonMask" is_bitfield="true">
 			Middle mouse button mask.
 		</constant>
-		<constant name="MOUSE_BUTTON_MASK_XBUTTON1" value="128" enum="MouseButton">
+		<constant name="MOUSE_BUTTON_MASK_MB_XBUTTON1" value="128" enum="MouseButtonMask" is_bitfield="true">
 			Extra mouse button 1 mask.
 		</constant>
-		<constant name="MOUSE_BUTTON_MASK_XBUTTON2" value="256" enum="MouseButton">
+		<constant name="MOUSE_BUTTON_MASK_MB_XBUTTON2" value="256" enum="MouseButtonMask" is_bitfield="true">
 			Extra mouse button 2 mask.
 		</constant>
 		<constant name="JOY_BUTTON_INVALID" value="-1" enum="JoyButton">
@@ -2840,111 +2840,111 @@
 		</constant>
 		<constant name="PROPERTY_HINT_MAX" value="45" enum="PropertyHint">
 		</constant>
-		<constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags" is_bitfield="true">
 			The property is not stored, and does not display in the editor. This is the default for non-exported properties.
 		</constant>
-		<constant name="PROPERTY_USAGE_STORAGE" value="2" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_STORAGE" value="2" enum="PropertyUsageFlags" is_bitfield="true">
 			The property is serialized and saved in the scene file (default).
 		</constant>
-		<constant name="PROPERTY_USAGE_EDITOR" value="4" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_EDITOR" value="4" enum="PropertyUsageFlags" is_bitfield="true">
 			The property is shown in the [EditorInspector] (default).
 		</constant>
-		<constant name="PROPERTY_USAGE_CHECKABLE" value="8" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_CHECKABLE" value="8" enum="PropertyUsageFlags" is_bitfield="true">
 			The property can be checked in the [EditorInspector].
 		</constant>
-		<constant name="PROPERTY_USAGE_CHECKED" value="16" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_CHECKED" value="16" enum="PropertyUsageFlags" is_bitfield="true">
 			The property is checked in the [EditorInspector].
 		</constant>
-		<constant name="PROPERTY_USAGE_INTERNATIONALIZED" value="32" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_INTERNATIONALIZED" value="32" enum="PropertyUsageFlags" is_bitfield="true">
 			The property is a translatable string.
 		</constant>
-		<constant name="PROPERTY_USAGE_GROUP" value="64" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_GROUP" value="64" enum="PropertyUsageFlags" is_bitfield="true">
 			Used to group properties together in the editor. See [EditorInspector].
 		</constant>
-		<constant name="PROPERTY_USAGE_CATEGORY" value="128" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_CATEGORY" value="128" enum="PropertyUsageFlags" is_bitfield="true">
 			Used to categorize properties together in the editor.
 		</constant>
-		<constant name="PROPERTY_USAGE_SUBGROUP" value="256" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_SUBGROUP" value="256" enum="PropertyUsageFlags" is_bitfield="true">
 			Used to group properties together in the editor in a subgroup (under a group). See [EditorInspector].
 		</constant>
-		<constant name="PROPERTY_USAGE_CLASS_IS_BITFIELD" value="512" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_CLASS_IS_BITFIELD" value="512" enum="PropertyUsageFlags" is_bitfield="true">
 		</constant>
-		<constant name="PROPERTY_USAGE_NO_INSTANCE_STATE" value="1024" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_NO_INSTANCE_STATE" value="1024" enum="PropertyUsageFlags" is_bitfield="true">
 			The property does not save its state in [PackedScene].
 		</constant>
-		<constant name="PROPERTY_USAGE_RESTART_IF_CHANGED" value="2048" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_RESTART_IF_CHANGED" value="2048" enum="PropertyUsageFlags" is_bitfield="true">
 			Editing the property prompts the user for restarting the editor.
 		</constant>
-		<constant name="PROPERTY_USAGE_SCRIPT_VARIABLE" value="4096" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_SCRIPT_VARIABLE" value="4096" enum="PropertyUsageFlags" is_bitfield="true">
 			The property is a script variable which should be serialized and saved in the scene file.
 		</constant>
-		<constant name="PROPERTY_USAGE_STORE_IF_NULL" value="8192" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_STORE_IF_NULL" value="8192" enum="PropertyUsageFlags" is_bitfield="true">
 		</constant>
-		<constant name="PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED" value="16384" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED" value="16384" enum="PropertyUsageFlags" is_bitfield="true">
 		</constant>
-		<constant name="PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE" value="32768" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE" value="32768" enum="PropertyUsageFlags" is_bitfield="true">
 		</constant>
-		<constant name="PROPERTY_USAGE_CLASS_IS_ENUM" value="65536" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_CLASS_IS_ENUM" value="65536" enum="PropertyUsageFlags" is_bitfield="true">
 		</constant>
-		<constant name="PROPERTY_USAGE_NIL_IS_VARIANT" value="131072" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_NIL_IS_VARIANT" value="131072" enum="PropertyUsageFlags" is_bitfield="true">
 		</constant>
-		<constant name="PROPERTY_USAGE_INTERNAL" value="262144" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_INTERNAL" value="262144" enum="PropertyUsageFlags" is_bitfield="true">
 		</constant>
-		<constant name="PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE" value="524288" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE" value="524288" enum="PropertyUsageFlags" is_bitfield="true">
 			If the property is a [Resource], a new copy of it is always created when calling [method Node.duplicate] or [method Resource.duplicate].
 		</constant>
-		<constant name="PROPERTY_USAGE_HIGH_END_GFX" value="1048576" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_HIGH_END_GFX" value="1048576" enum="PropertyUsageFlags" is_bitfield="true">
 			The property is only shown in the editor if modern renderers are supported (GLES3 is excluded).
 		</constant>
-		<constant name="PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT" value="2097152" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT" value="2097152" enum="PropertyUsageFlags" is_bitfield="true">
 		</constant>
-		<constant name="PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT" value="4194304" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT" value="4194304" enum="PropertyUsageFlags" is_bitfield="true">
 		</constant>
-		<constant name="PROPERTY_USAGE_KEYING_INCREMENTS" value="8388608" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_KEYING_INCREMENTS" value="8388608" enum="PropertyUsageFlags" is_bitfield="true">
 		</constant>
-		<constant name="PROPERTY_USAGE_DEFERRED_SET_RESOURCE" value="16777216" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_DEFERRED_SET_RESOURCE" value="16777216" enum="PropertyUsageFlags" is_bitfield="true">
 		</constant>
-		<constant name="PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT" value="33554432" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT" value="33554432" enum="PropertyUsageFlags" is_bitfield="true">
 		</constant>
-		<constant name="PROPERTY_USAGE_EDITOR_BASIC_SETTING" value="67108864" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_EDITOR_BASIC_SETTING" value="67108864" enum="PropertyUsageFlags" is_bitfield="true">
 		</constant>
-		<constant name="PROPERTY_USAGE_READ_ONLY" value="134217728" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_READ_ONLY" value="134217728" enum="PropertyUsageFlags" is_bitfield="true">
 			The property is read-only in the [EditorInspector].
 		</constant>
-		<constant name="PROPERTY_USAGE_ARRAY" value="268435456" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_ARRAY" value="268435456" enum="PropertyUsageFlags" is_bitfield="true">
 			The property is an array.
 		</constant>
-		<constant name="PROPERTY_USAGE_DEFAULT" value="6" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_DEFAULT" value="6" enum="PropertyUsageFlags" is_bitfield="true">
 			Default usage (storage, editor and network).
 		</constant>
-		<constant name="PROPERTY_USAGE_DEFAULT_INTL" value="38" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_DEFAULT_INTL" value="38" enum="PropertyUsageFlags" is_bitfield="true">
 			Default usage for translatable strings (storage, editor, network and internationalized).
 		</constant>
-		<constant name="PROPERTY_USAGE_NO_EDITOR" value="2" enum="PropertyUsageFlags">
+		<constant name="PROPERTY_USAGE_NO_EDITOR" value="2" enum="PropertyUsageFlags" is_bitfield="true">
 			Default usage but without showing the property in the editor (storage, network).
 		</constant>
-		<constant name="METHOD_FLAG_NORMAL" value="1" enum="MethodFlags">
+		<constant name="METHOD_FLAG_NORMAL" value="1" enum="MethodFlags" is_bitfield="true">
 			Flag for a normal method.
 		</constant>
-		<constant name="METHOD_FLAG_EDITOR" value="2" enum="MethodFlags">
+		<constant name="METHOD_FLAG_EDITOR" value="2" enum="MethodFlags" is_bitfield="true">
 			Flag for an editor method.
 		</constant>
-		<constant name="METHOD_FLAG_CONST" value="4" enum="MethodFlags">
+		<constant name="METHOD_FLAG_CONST" value="4" enum="MethodFlags" is_bitfield="true">
 			Flag for a constant method.
 		</constant>
-		<constant name="METHOD_FLAG_VIRTUAL" value="8" enum="MethodFlags">
+		<constant name="METHOD_FLAG_VIRTUAL" value="8" enum="MethodFlags" is_bitfield="true">
 			Flag for a virtual method.
 		</constant>
-		<constant name="METHOD_FLAG_VARARG" value="16" enum="MethodFlags">
+		<constant name="METHOD_FLAG_VARARG" value="16" enum="MethodFlags" is_bitfield="true">
 			Flag for a method with a variable number of arguments.
 		</constant>
-		<constant name="METHOD_FLAG_STATIC" value="32" enum="MethodFlags">
+		<constant name="METHOD_FLAG_STATIC" value="32" enum="MethodFlags" is_bitfield="true">
 			Flag for a static method.
 		</constant>
-		<constant name="METHOD_FLAG_OBJECT_CORE" value="64" enum="MethodFlags">
+		<constant name="METHOD_FLAG_OBJECT_CORE" value="64" enum="MethodFlags" is_bitfield="true">
 			Used internally. Allows to not dump core virtual methods (such as [method Object._notification]) to the JSON API.
 		</constant>
-		<constant name="METHOD_FLAGS_DEFAULT" value="1" enum="MethodFlags">
+		<constant name="METHOD_FLAGS_DEFAULT" value="1" enum="MethodFlags" is_bitfield="true">
 			Default method flags (normal).
 		</constant>
 		<constant name="TYPE_NIL" value="0" enum="Variant.Type">

+ 1 - 1
doc/classes/BaseButton.xml

@@ -50,7 +50,7 @@
 		<member name="button_group" type="ButtonGroup" setter="set_button_group" getter="get_button_group">
 			The [ButtonGroup] associated with the button. Not to be confused with node groups.
 		</member>
-		<member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" enum="MouseButton" default="1">
+		<member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" enum="MouseButtonMask" default="0">
 			Binary mask to choose which mouse buttons this button will respond to.
 			To allow both left-click and right-click, use [code]MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT[/code].
 		</member>

+ 1 - 1
doc/classes/DisplayServer.xml

@@ -785,7 +785,7 @@
 			</description>
 		</method>
 		<method name="mouse_get_button_state" qualifiers="const">
-			<return type="int" enum="MouseButton" />
+			<return type="int" enum="MouseButtonMask" />
 			<description>
 				Returns the current state of mouse buttons (whether each button is pressed) as a bitmask. If multiple mouse buttons are pressed at the same time, the bits are added together. Equivalent to [method Input.get_mouse_button_mask].
 			</description>

+ 1 - 1
doc/classes/Input.xml

@@ -155,7 +155,7 @@
 			</description>
 		</method>
 		<method name="get_mouse_button_mask" qualifiers="const">
-			<return type="int" enum="MouseButton" />
+			<return type="int" enum="MouseButtonMask" />
 			<description>
 				Returns mouse buttons as a bitmask. If multiple mouse buttons are pressed at the same time, the bits are added together. Equivalent to [method DisplayServer.mouse_get_button_state].
 			</description>

+ 1 - 1
doc/classes/InputEventMouse.xml

@@ -10,7 +10,7 @@
 		<link title="InputEvent">$DOCS_URL/tutorials/inputs/inputevent.html</link>
 	</tutorials>
 	<members>
-		<member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" enum="MouseButton" default="0">
+		<member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" enum="MouseButtonMask" default="0">
 			The mouse button mask identifier, one of or a bitwise combination of the [enum MouseButton] button masks.
 		</member>
 		<member name="global_position" type="Vector2" setter="set_global_position" getter="get_global_position" default="Vector2(0, 0)">

+ 2 - 2
editor/animation_track_editor.cpp

@@ -2919,7 +2919,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 		}
 	}
 
-	if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE && moving_selection_attempt) {
+	if (mm.is_valid() && mm->get_button_mask().has_flag(MouseButtonMask::LEFT) && moving_selection_attempt) {
 		if (!moving_selection) {
 			moving_selection = true;
 			emit_signal(SNAME("move_selection_begin"));
@@ -5309,7 +5309,7 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
 	Ref<InputEventMouseMotion> mm = p_event;
 
 	if (mm.is_valid() && box_selecting) {
-		if ((mm->get_button_mask() & MouseButton::MASK_LEFT) == MouseButton::NONE) {
+		if (!mm->get_button_mask().has_flag(MouseButtonMask::LEFT)) {
 			// No longer.
 			box_selection->hide();
 			box_selecting = false;

+ 1 - 1
editor/debugger/editor_profiler.cpp

@@ -468,7 +468,7 @@ void EditorProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) {
 			x = frame_metrics.size() - 1;
 		}
 
-		if (mb.is_valid() || (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+		if (mb.is_valid() || (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 			updating_frame = true;
 
 			if (x < total_metrics) {

+ 1 - 1
editor/debugger/editor_visual_profiler.cpp

@@ -544,7 +544,7 @@ void EditorVisualProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) {
 			hover_metric = -1;
 		}
 
-		if (mb.is_valid() || (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+		if (mb.is_valid() || mm->get_button_mask().has_flag(MouseButtonMask::LEFT)) {
 			//cursor_metric=x;
 			updating_frame = true;
 

+ 1 - 0
editor/doc_tools.cpp

@@ -845,6 +845,7 @@ void DocTools::generate(bool p_basic_types) {
 		for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) {
 			DocData::ConstantDoc cd;
 			cd.name = CoreConstants::get_global_constant_name(i);
+			cd.is_bitfield = CoreConstants::is_global_constant_bitfield(i);
 			if (!CoreConstants::get_ignore_value_in_docs(i)) {
 				cd.value = itos(CoreConstants::get_global_constant_value(i));
 				cd.is_value_valid = true;

+ 1 - 1
editor/editor_inspector.cpp

@@ -618,7 +618,7 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) {
 		if (is_layout_rtl()) {
 			mpos.x = get_size().x - mpos.x;
 		}
-		bool button_left = (me->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE;
+		bool button_left = me->get_button_mask().has_flag(MouseButtonMask::LEFT);
 
 		bool new_keying_hover = keying_rect.has_point(mpos) && !button_left;
 		if (new_keying_hover != keying_hover) {

+ 1 - 1
editor/editor_properties.cpp

@@ -1577,7 +1577,7 @@ void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) {
 
 	const Ref<InputEventMouseMotion> mm = p_ev;
 
-	if (dragging && mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+	if (dragging && mm.is_valid() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 		float rel = mm->get_relative().x;
 		if (rel == 0) {
 			return;

+ 1 - 1
editor/editor_title_bar.cpp

@@ -37,7 +37,7 @@ void EditorTitleBar::input(const Ref<InputEvent> &p_event) {
 
 	Ref<InputEventMouseMotion> mm = p_event;
 	if (mm.is_valid() && moving) {
-		if ((mm->get_button_mask() & MouseButton::LEFT) == MouseButton::LEFT) {
+		if (mm->get_button_mask().has_flag(MouseButtonMask::LEFT)) {
 			Window *w = Object::cast_to<Window>(get_viewport());
 			if (w) {
 				Point2 mouse = DisplayServer::get_singleton()->mouse_get_position();

+ 1 - 1
editor/import/scene_import_settings.cpp

@@ -849,7 +849,7 @@ void SceneImportSettings::_viewport_input(const Ref<InputEvent> &p_input) {
 		zoom = &md.cam_zoom;
 	}
 	Ref<InputEventMouseMotion> mm = p_input;
-	if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+	if (mm.is_valid() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 		(*rot_x) -= mm->get_relative().y * 0.01 * EDSCALE;
 		(*rot_y) -= mm->get_relative().x * 0.01 * EDSCALE;
 		(*rot_x) = CLAMP((*rot_x), -Math_PI / 2, Math_PI / 2);

+ 1 - 1
editor/plugins/abstract_polygon_2d_editor.cpp

@@ -410,7 +410,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
 	if (mm.is_valid()) {
 		Vector2 gpoint = mm->get_position();
 
-		if (edited_point.valid() && (wip_active || (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE)) {
+		if (edited_point.valid() && (wip_active || mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 			Vector2 cpoint = _get_node()->to_local(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)));
 
 			//Move the point in a single axis. Should only work when editing a polygon and while holding shift.

+ 1 - 1
editor/plugins/animation_blend_space_1d_editor.cpp

@@ -200,7 +200,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
 		_update_edited_point_pos();
 	}
 
-	if (mm.is_valid() && tool_blend->is_pressed() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+	if (mm.is_valid() && tool_blend->is_pressed() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 		float blend_pos = mm->get_position().x / blend_space_draw->get_size().x;
 		blend_pos *= blend_space->get_max_space() - blend_space->get_min_space();
 		blend_pos += blend_space->get_min_space();

+ 1 - 1
editor/plugins/animation_blend_space_2d_editor.cpp

@@ -308,7 +308,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
 		blend_space_draw->queue_redraw();
 	}
 
-	if (mm.is_valid() && tool_blend->is_pressed() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+	if (mm.is_valid() && tool_blend->is_pressed() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 		Vector2 blend_pos = (mm->get_position() / blend_space_draw->get_size());
 		blend_pos.y = 1.0 - blend_pos.y;
 		blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space());

+ 1 - 1
editor/plugins/animation_state_machine_editor.cpp

@@ -337,7 +337,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
 	Ref<InputEventMouseMotion> mm = p_event;
 
 	// Pan window
-	if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE) {
+	if (mm.is_valid() && mm->get_button_mask().has_flag(MouseButtonMask::MIDDLE)) {
 		h_scroll->set_value(h_scroll->get_value() - mm->get_relative().x);
 		v_scroll->set_value(v_scroll->get_value() - mm->get_relative().y);
 	}

+ 1 - 1
editor/plugins/canvas_item_editor_plugin.cpp

@@ -1322,7 +1322,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
 	// Drag the pivot (in pivot mode / with V key)
 	if (drag_type == DRAG_NONE) {
 		if ((b.is_valid() && b->is_pressed() && b->get_button_index() == MouseButton::LEFT && tool == TOOL_EDIT_PIVOT) ||
-				(k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == Key::V && tool == TOOL_SELECT && k->get_modifiers_mask() == Key::NONE)) {
+				(k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == Key::V && tool == TOOL_SELECT && k->get_modifiers_mask().is_empty())) {
 			List<CanvasItem *> selection = _get_edited_canvas_items();
 
 			// Filters the selection with nodes that allow setting the pivot

+ 1 - 1
editor/plugins/material_editor_plugin.cpp

@@ -44,7 +44,7 @@ void MaterialEditor::gui_input(const Ref<InputEvent> &p_event) {
 	ERR_FAIL_COND(p_event.is_null());
 
 	Ref<InputEventMouseMotion> mm = p_event;
-	if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+	if (mm.is_valid() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 		rot.x -= mm->get_relative().y * 0.01;
 		rot.y -= mm->get_relative().x * 0.01;
 

+ 1 - 1
editor/plugins/mesh_editor_plugin.cpp

@@ -39,7 +39,7 @@ void MeshEditor::gui_input(const Ref<InputEvent> &p_event) {
 	ERR_FAIL_COND(p_event.is_null());
 
 	Ref<InputEventMouseMotion> mm = p_event;
-	if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+	if (mm.is_valid() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 		rot_x -= mm->get_relative().y * 0.01;
 		rot_y -= mm->get_relative().x * 0.01;
 		if (rot_x < -Math_PI / 2) {

+ 5 - 5
editor/plugins/node_3d_editor_plugin.cpp

@@ -1911,7 +1911,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
 			}
 		}
 
-		if (spatial_editor->get_current_hover_gizmo().is_null() && (m->get_button_mask() & MouseButton::MASK_LEFT) == MouseButton::NONE && !_edit.gizmo.is_valid()) {
+		if (spatial_editor->get_current_hover_gizmo().is_null() && !m->get_button_mask().has_flag(MouseButtonMask::LEFT) && !_edit.gizmo.is_valid()) {
 			_transform_gizmo_select(_edit.mouse_pos, true);
 		}
 
@@ -1924,7 +1924,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
 			String n = _edit.gizmo->get_handle_name(_edit.gizmo_handle, _edit.gizmo_handle_secondary);
 			set_message(n + ": " + String(v));
 
-		} else if ((m->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE || _edit.instant) {
+		} else if (m->get_button_mask().has_flag(MouseButtonMask::LEFT) || _edit.instant) {
 			if (nav_scheme == NAVIGATION_MAYA && m->is_alt_pressed()) {
 				nav_mode = NAVIGATION_ORBIT;
 			} else if (nav_scheme == NAVIGATION_MODO && m->is_alt_pressed() && m->is_shift_pressed()) {
@@ -1963,7 +1963,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
 
 				update_transform(m->get_position(), _get_key_modifier(m) == Key::SHIFT);
 			}
-		} else if ((m->get_button_mask() & MouseButton::MASK_RIGHT) != MouseButton::NONE || freelook_active) {
+		} else if (m->get_button_mask().has_flag(MouseButtonMask::RIGHT) || freelook_active) {
 			if (nav_scheme == NAVIGATION_MAYA && m->is_alt_pressed()) {
 				nav_mode = NAVIGATION_ZOOM;
 			} else if (freelook_active) {
@@ -1972,7 +1972,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
 				nav_mode = NAVIGATION_PAN;
 			}
 
-		} else if ((m->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE) {
+		} else if (m->get_button_mask().has_flag(MouseButtonMask::MIDDLE)) {
 			const Key mod = _get_key_modifier(m);
 			if (nav_scheme == NAVIGATION_GODOT) {
 				if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) {
@@ -7995,7 +7995,7 @@ void Node3DEditor::_update_preview_environment() {
 
 void Node3DEditor::_sun_direction_input(const Ref<InputEvent> &p_event) {
 	Ref<InputEventMouseMotion> mm = p_event;
-	if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+	if (mm.is_valid() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 		sun_rotation.x += mm->get_relative().y * (0.02 * EDSCALE);
 		sun_rotation.y -= mm->get_relative().x * (0.02 * EDSCALE);
 		sun_rotation.x = CLAMP(sun_rotation.x, -Math_TAU / 4, Math_TAU / 4);

+ 1 - 1
editor/plugins/polygon_3d_editor_plugin.cpp

@@ -313,7 +313,7 @@ EditorPlugin::AfterGUIInput Polygon3DEditor::forward_3d_gui_input(Camera3D *p_ca
 	Ref<InputEventMouseMotion> mm = p_event;
 
 	if (mm.is_valid()) {
-		if (edited_point != -1 && (wip_active || (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE)) {
+		if (edited_point != -1 && (wip_active || mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 			Vector2 gpoint = mm->get_position();
 
 			Vector3 ray_from = p_camera->project_ray_origin(gpoint);

+ 2 - 2
editor/plugins/sprite_frames_editor_plugin.cpp

@@ -197,7 +197,7 @@ void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) {
 	}
 
 	const Ref<InputEventMouseMotion> mm = p_event;
-	if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+	if (mm.is_valid() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 		// Select by holding down the mouse button on frames.
 		const int idx = _sheet_preview_position_to_frame_index(mm->get_position());
 
@@ -238,7 +238,7 @@ void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) {
 	}
 
 	const Ref<InputEventMouseMotion> mm = p_event;
-	if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE) {
+	if (mm.is_valid() && mm->get_button_mask().has_flag(MouseButtonMask::MIDDLE)) {
 		const Vector2 dragged = Input::get_singleton()->warp_mouse_motion(mm, split_sheet_scroll->get_global_rect());
 		split_sheet_scroll->set_h_scroll(split_sheet_scroll->get_h_scroll() - dragged.x);
 		split_sheet_scroll->set_v_scroll(split_sheet_scroll->get_v_scroll() - dragged.y);

+ 1 - 1
editor/plugins/texture_layered_editor_plugin.cpp

@@ -36,7 +36,7 @@ void TextureLayeredEditor::gui_input(const Ref<InputEvent> &p_event) {
 	ERR_FAIL_COND(p_event.is_null());
 
 	Ref<InputEventMouseMotion> mm = p_event;
-	if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+	if (mm.is_valid() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 		y_rot += -mm->get_relative().x * 0.01;
 		x_rot += mm->get_relative().y * 0.01;
 		_update_material();

+ 20 - 20
platform/android/android_input_handler.cpp

@@ -225,7 +225,7 @@ void AndroidInputHandler::process_touch_event(int p_event, int p_pointer, const
 	}
 }
 
-void AndroidInputHandler::_parse_mouse_event_info(MouseButton event_buttons_mask, bool p_pressed, bool p_double_click, bool p_source_mouse_relative) {
+void AndroidInputHandler::_parse_mouse_event_info(BitField<MouseButtonMask> event_buttons_mask, bool p_pressed, bool p_double_click, bool p_source_mouse_relative) {
 	if (!mouse_event_info.valid) {
 		return;
 	}
@@ -242,7 +242,7 @@ void AndroidInputHandler::_parse_mouse_event_info(MouseButton event_buttons_mask
 		hover_prev_pos = mouse_event_info.pos;
 	}
 	ev->set_pressed(p_pressed);
-	MouseButton changed_button_mask = MouseButton(buttons_state ^ event_buttons_mask);
+	BitField<MouseButtonMask> changed_button_mask = BitField<MouseButtonMask>(buttons_state.operator int64_t() ^ event_buttons_mask.operator int64_t());
 
 	buttons_state = event_buttons_mask;
 
@@ -253,12 +253,12 @@ void AndroidInputHandler::_parse_mouse_event_info(MouseButton event_buttons_mask
 }
 
 void AndroidInputHandler::_release_mouse_event_info(bool p_source_mouse_relative) {
-	_parse_mouse_event_info(MouseButton::NONE, false, false, p_source_mouse_relative);
+	_parse_mouse_event_info(BitField<MouseButtonMask>(), false, false, p_source_mouse_relative);
 	mouse_event_info.valid = false;
 }
 
 void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_android_buttons_mask, Point2 p_event_pos, Vector2 p_delta, bool p_double_click, bool p_source_mouse_relative) {
-	MouseButton event_buttons_mask = _android_button_mask_to_godot_button_mask(p_event_android_buttons_mask);
+	BitField<MouseButtonMask> event_buttons_mask = _android_button_mask_to_godot_button_mask(p_event_android_buttons_mask);
 	switch (p_event_action) {
 		case AMOTION_EVENT_ACTION_HOVER_MOVE: // hover move
 		case AMOTION_EVENT_ACTION_HOVER_ENTER: // hover enter
@@ -342,11 +342,11 @@ void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_an
 	}
 }
 
-void AndroidInputHandler::_wheel_button_click(MouseButton event_buttons_mask, const Ref<InputEventMouseButton> &ev, MouseButton wheel_button, float factor) {
+void AndroidInputHandler::_wheel_button_click(BitField<MouseButtonMask> event_buttons_mask, const Ref<InputEventMouseButton> &ev, MouseButton wheel_button, float factor) {
 	Ref<InputEventMouseButton> evd = ev->duplicate();
 	_set_key_modifier_state(evd);
 	evd->set_button_index(wheel_button);
-	evd->set_button_mask(MouseButton(event_buttons_mask ^ mouse_button_to_mask(wheel_button)));
+	evd->set_button_mask(BitField<MouseButtonMask>(event_buttons_mask.operator int64_t() ^ int64_t(mouse_button_to_mask(wheel_button))));
 	evd->set_factor(factor);
 	Input::get_singleton()->parse_input_event(evd);
 	Ref<InputEventMouseButton> evdd = evd->duplicate();
@@ -373,39 +373,39 @@ void AndroidInputHandler::process_pan(Point2 p_pos, Vector2 p_delta) {
 	Input::get_singleton()->parse_input_event(pan_event);
 }
 
-MouseButton AndroidInputHandler::_button_index_from_mask(MouseButton button_mask) {
-	switch (button_mask) {
-		case MouseButton::MASK_LEFT:
+MouseButton AndroidInputHandler::_button_index_from_mask(BitField<MouseButtonMask> button_mask) {
+	switch (MouseButtonMask(button_mask.operator int64_t())) {
+		case MouseButtonMask::LEFT:
 			return MouseButton::LEFT;
-		case MouseButton::MASK_RIGHT:
+		case MouseButtonMask::RIGHT:
 			return MouseButton::RIGHT;
-		case MouseButton::MASK_MIDDLE:
+		case MouseButtonMask::MIDDLE:
 			return MouseButton::MIDDLE;
-		case MouseButton::MASK_XBUTTON1:
+		case MouseButtonMask::MB_XBUTTON1:
 			return MouseButton::MB_XBUTTON1;
-		case MouseButton::MASK_XBUTTON2:
+		case MouseButtonMask::MB_XBUTTON2:
 			return MouseButton::MB_XBUTTON2;
 		default:
 			return MouseButton::NONE;
 	}
 }
 
-MouseButton AndroidInputHandler::_android_button_mask_to_godot_button_mask(int android_button_mask) {
-	MouseButton godot_button_mask = MouseButton::NONE;
+BitField<MouseButtonMask> AndroidInputHandler::_android_button_mask_to_godot_button_mask(int android_button_mask) {
+	BitField<MouseButtonMask> godot_button_mask;
 	if (android_button_mask & AMOTION_EVENT_BUTTON_PRIMARY) {
-		godot_button_mask |= MouseButton::MASK_LEFT;
+		godot_button_mask.set_flag(MouseButtonMask::LEFT);
 	}
 	if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) {
-		godot_button_mask |= MouseButton::MASK_RIGHT;
+		godot_button_mask.set_flag(MouseButtonMask::RIGHT);
 	}
 	if (android_button_mask & AMOTION_EVENT_BUTTON_TERTIARY) {
-		godot_button_mask |= MouseButton::MASK_MIDDLE;
+		godot_button_mask.set_flag(MouseButtonMask::MIDDLE);
 	}
 	if (android_button_mask & AMOTION_EVENT_BUTTON_BACK) {
-		godot_button_mask |= MouseButton::MASK_XBUTTON1;
+		godot_button_mask.set_flag(MouseButtonMask::MB_XBUTTON1);
 	}
 	if (android_button_mask & AMOTION_EVENT_BUTTON_FORWARD) {
-		godot_button_mask |= MouseButton::MASK_XBUTTON2;
+		godot_button_mask.set_flag(MouseButtonMask::MB_XBUTTON2);
 	}
 
 	return godot_button_mask;

+ 6 - 6
platform/android/android_input_handler.h

@@ -61,7 +61,7 @@ public:
 		int index = 0; // Can be either JoyAxis or JoyButton.
 		bool pressed = false;
 		float value = 0;
-		HatMask hat = HatMask::CENTER;
+		BitField<HatMask> hat;
 	};
 
 private:
@@ -70,7 +70,7 @@ private:
 	bool control_mem = false;
 	bool meta_mem = false;
 
-	MouseButton buttons_state = MouseButton::NONE;
+	BitField<MouseButtonMask> buttons_state;
 
 	Vector<TouchPos> touch;
 	MouseEventInfo mouse_event_info;
@@ -78,12 +78,12 @@ private:
 
 	void _set_key_modifier_state(Ref<InputEventWithModifiers> ev);
 
-	static MouseButton _button_index_from_mask(MouseButton button_mask);
-	static MouseButton _android_button_mask_to_godot_button_mask(int android_button_mask);
+	static MouseButton _button_index_from_mask(BitField<MouseButtonMask> button_mask);
+	static BitField<MouseButtonMask> _android_button_mask_to_godot_button_mask(int android_button_mask);
 
-	void _wheel_button_click(MouseButton event_buttons_mask, const Ref<InputEventMouseButton> &ev, MouseButton wheel_button, float factor);
+	void _wheel_button_click(BitField<MouseButtonMask> event_buttons_mask, const Ref<InputEventMouseButton> &ev, MouseButton wheel_button, float factor);
 
-	void _parse_mouse_event_info(MouseButton event_buttons_mask, bool p_pressed, bool p_double_click, bool p_source_mouse_relative);
+	void _parse_mouse_event_info(BitField<MouseButtonMask> event_buttons_mask, bool p_pressed, bool p_double_click, bool p_source_mouse_relative);
 
 	void _release_mouse_event_info(bool p_source_mouse_relative = false);
 

+ 2 - 2
platform/android/display_server_android.cpp

@@ -624,8 +624,8 @@ Point2i DisplayServerAndroid::mouse_get_position() const {
 	return Input::get_singleton()->get_mouse_position();
 }
 
-MouseButton DisplayServerAndroid::mouse_get_button_state() const {
-	return (MouseButton)Input::get_singleton()->get_mouse_button_mask();
+BitField<MouseButtonMask> DisplayServerAndroid::mouse_get_button_state() const {
+	return Input::get_singleton()->get_mouse_button_mask();
 }
 
 void DisplayServerAndroid::_cursor_set_shape_helper(CursorShape p_shape, bool force) {

+ 1 - 1
platform/android/display_server_android.h

@@ -207,7 +207,7 @@ public:
 	void notify_surface_changed(int p_width, int p_height);
 
 	virtual Point2i mouse_get_position() const override;
-	virtual MouseButton mouse_get_button_state() const override;
+	virtual BitField<MouseButtonMask> mouse_get_button_state() const override;
 
 	void reset_swap_buffers_flag();
 	bool should_swap_buffers() const;

+ 5 - 5
platform/android/java_godot_lib_jni.cpp

@@ -353,19 +353,19 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, j
 	AndroidInputHandler::JoypadEvent jevent;
 	jevent.device = p_device;
 	jevent.type = AndroidInputHandler::JOY_EVENT_HAT;
-	HatMask hat = HatMask::CENTER;
+	BitField<HatMask> hat;
 	if (p_hat_x != 0) {
 		if (p_hat_x < 0) {
-			hat |= HatMask::LEFT;
+			hat.set_flag(HatMask::LEFT);
 		} else {
-			hat |= HatMask::RIGHT;
+			hat.set_flag(HatMask::RIGHT);
 		}
 	}
 	if (p_hat_y != 0) {
 		if (p_hat_y < 0) {
-			hat |= HatMask::UP;
+			hat.set_flag(HatMask::UP);
 		} else {
-			hat |= HatMask::DOWN;
+			hat.set_flag(HatMask::DOWN);
 		}
 	}
 	jevent.hat = hat;

+ 15 - 9
platform/linuxbsd/joypad_linux.cpp

@@ -59,7 +59,7 @@ JoypadLinux::Joypad::~Joypad() {
 }
 
 void JoypadLinux::Joypad::reset() {
-	dpad = HatMask::CENTER;
+	dpad = 0;
 	fd = -1;
 	for (int i = 0; i < MAX_ABS; i++) {
 		abs_map[i] = -1;
@@ -485,27 +485,33 @@ void JoypadLinux::process_joypads() {
 						case ABS_HAT0X:
 							if (joypad_event.value != 0) {
 								if (joypad_event.value < 0) {
-									joypad.dpad = (HatMask)((joypad.dpad | HatMask::LEFT) & ~HatMask::RIGHT);
+									joypad.dpad.set_flag(HatMask::LEFT);
+									joypad.dpad.clear_flag(HatMask::RIGHT);
 								} else {
-									joypad.dpad = (HatMask)((joypad.dpad | HatMask::RIGHT) & ~HatMask::LEFT);
+									joypad.dpad.set_flag(HatMask::RIGHT);
+									joypad.dpad.clear_flag(HatMask::LEFT);
 								}
 							} else {
-								joypad.dpad &= ~(HatMask::LEFT | HatMask::RIGHT);
+								joypad.dpad.clear_flag(HatMask::LEFT);
+								joypad.dpad.clear_flag(HatMask::RIGHT);
 							}
-							input->joy_hat(i, (HatMask)joypad.dpad);
+							input->joy_hat(i, joypad.dpad);
 							break;
 
 						case ABS_HAT0Y:
 							if (joypad_event.value != 0) {
 								if (joypad_event.value < 0) {
-									joypad.dpad = (HatMask)((joypad.dpad | HatMask::UP) & ~HatMask::DOWN);
+									joypad.dpad.set_flag(HatMask::UP);
+									joypad.dpad.clear_flag(HatMask::DOWN);
 								} else {
-									joypad.dpad = (HatMask)((joypad.dpad | HatMask::DOWN) & ~HatMask::UP);
+									joypad.dpad.set_flag(HatMask::DOWN);
+									joypad.dpad.clear_flag(HatMask::UP);
 								}
 							} else {
-								joypad.dpad &= ~(HatMask::UP | HatMask::DOWN);
+								joypad.dpad.clear_flag(HatMask::UP);
+								joypad.dpad.clear_flag(HatMask::DOWN);
 							}
-							input->joy_hat(i, (HatMask)joypad.dpad);
+							input->joy_hat(i, joypad.dpad);
 							break;
 
 						default:

+ 1 - 1
platform/linuxbsd/joypad_linux.h

@@ -62,7 +62,7 @@ private:
 		float curr_axis[MAX_ABS];
 		int key_map[MAX_KEY];
 		int abs_map[MAX_ABS];
-		HatMask dpad = HatMask::CENTER;
+		BitField<HatMask> dpad;
 		int fd = -1;
 
 		String devpath;

+ 7 - 7
platform/linuxbsd/x11/display_server_x11.cpp

@@ -458,7 +458,7 @@ Point2i DisplayServerX11::mouse_get_position() const {
 	return Vector2i();
 }
 
-MouseButton DisplayServerX11::mouse_get_button_state() const {
+BitField<MouseButtonMask> DisplayServerX11::mouse_get_button_state() const {
 	return last_button_state;
 }
 
@@ -2843,13 +2843,13 @@ void DisplayServerX11::_get_key_modifier_state(unsigned int p_x11_state, Ref<Inp
 	state->set_meta_pressed((p_x11_state & Mod4Mask));
 }
 
-MouseButton DisplayServerX11::_get_mouse_button_state(MouseButton p_x11_button, int p_x11_type) {
-	MouseButton mask = mouse_button_to_mask(p_x11_button);
+BitField<MouseButtonMask> DisplayServerX11::_get_mouse_button_state(MouseButton p_x11_button, int p_x11_type) {
+	MouseButtonMask mask = mouse_button_to_mask(p_x11_button);
 
 	if (p_x11_type == ButtonPress) {
-		last_button_state |= mask;
+		last_button_state.set_flag(mask);
 	} else {
-		last_button_state &= ~mask;
+		last_button_state.clear_flag(mask);
 	}
 
 	return last_button_state;
@@ -4171,13 +4171,13 @@ void DisplayServerX11::process_events() {
 				if (xi.pressure_supported) {
 					mm->set_pressure(xi.pressure);
 				} else {
-					mm->set_pressure(bool(mouse_get_button_state() & MouseButton::MASK_LEFT) ? 1.0f : 0.0f);
+					mm->set_pressure(bool(mouse_get_button_state().has_flag(MouseButtonMask::LEFT)) ? 1.0f : 0.0f);
 				}
 				mm->set_tilt(xi.tilt);
 				mm->set_pen_inverted(xi.pen_inverted);
 
 				_get_key_modifier_state(event.xmotion.state, mm);
-				mm->set_button_mask((MouseButton)mouse_get_button_state());
+				mm->set_button_mask(mouse_get_button_state());
 				mm->set_position(pos);
 				mm->set_global_position(pos);
 				mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity());

+ 3 - 3
platform/linuxbsd/x11/display_server_x11.h

@@ -205,7 +205,7 @@ class DisplayServerX11 : public DisplayServer {
 	Point2i last_click_pos = Point2i(-100, -100);
 	uint64_t last_click_ms = 0;
 	MouseButton last_click_button_index = MouseButton::NONE;
-	MouseButton last_button_state = MouseButton::NONE;
+	BitField<MouseButtonMask> last_button_state;
 	bool app_focused = false;
 	uint64_t time_since_no_focus = 0;
 
@@ -234,7 +234,7 @@ class DisplayServerX11 : public DisplayServer {
 
 	Rect2i _screen_get_rect(int p_screen) const;
 
-	MouseButton _get_mouse_button_state(MouseButton p_x11_button, int p_x11_type);
+	BitField<MouseButtonMask> _get_mouse_button_state(MouseButton p_x11_button, int p_x11_type);
 	void _get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state);
 	void _flush_mouse_motion();
 
@@ -344,7 +344,7 @@ public:
 
 	virtual void warp_mouse(const Point2i &p_position) override;
 	virtual Point2i mouse_get_position() const override;
-	virtual MouseButton mouse_get_button_state() const override;
+	virtual BitField<MouseButtonMask> mouse_get_button_state() const override;
 
 	virtual void clipboard_set(const String &p_text) override;
 	virtual String clipboard_get() const override;

+ 3 - 3
platform/macos/display_server_macos.h

@@ -154,7 +154,7 @@ private:
 
 	CGEventSourceRef event_source;
 	MouseMode mouse_mode = MOUSE_MODE_VISIBLE;
-	MouseButton last_button_state = MouseButton::NONE;
+	BitField<MouseButtonMask> last_button_state;
 
 	bool drop_events = false;
 	bool in_dispatch_input_event = false;
@@ -317,8 +317,8 @@ public:
 	bool update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSPoint &r_mpos, NSTimeInterval p_timestamp);
 	virtual void warp_mouse(const Point2i &p_position) override;
 	virtual Point2i mouse_get_position() const override;
-	void mouse_set_button_state(MouseButton p_state);
-	virtual MouseButton mouse_get_button_state() const override;
+	void mouse_set_button_state(BitField<MouseButtonMask> p_state);
+	virtual BitField<MouseButtonMask> mouse_get_button_state() const override;
 
 	virtual void clipboard_set(const String &p_text) override;
 	virtual String clipboard_get() const override;

+ 2 - 2
platform/macos/display_server_macos.mm

@@ -2034,11 +2034,11 @@ Point2i DisplayServerMacOS::mouse_get_position() const {
 	return Vector2i();
 }
 
-void DisplayServerMacOS::mouse_set_button_state(MouseButton p_state) {
+void DisplayServerMacOS::mouse_set_button_state(BitField<MouseButtonMask> p_state) {
 	last_button_state = p_state;
 }
 
-MouseButton DisplayServerMacOS::mouse_get_button_state() const {
+BitField<MouseButtonMask> DisplayServerMacOS::mouse_get_button_state() const {
 	return last_button_state;
 }
 

+ 1 - 1
platform/macos/godot_content_view.h

@@ -66,7 +66,7 @@
 
 - (void)processScrollEvent:(NSEvent *)event button:(MouseButton)button factor:(double)factor;
 - (void)processPanEvent:(NSEvent *)event dx:(double)dx dy:(double)dy;
-- (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index mask:(MouseButton)mask pressed:(bool)pressed;
+- (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index pressed:(bool)pressed;
 - (void)setWindowID:(DisplayServer::WindowID)wid;
 - (void)updateLayerDelegate;
 - (void)cancelComposition;

+ 22 - 19
platform/macos/godot_content_view.mm

@@ -371,19 +371,21 @@
 	ds->cursor_update_shape();
 }
 
-- (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index mask:(MouseButton)mask pressed:(bool)pressed {
+- (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index pressed:(bool)pressed {
 	DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
 	if (!ds || !ds->has_window(window_id)) {
 		return;
 	}
 
 	DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
-	MouseButton last_button_state = ds->mouse_get_button_state();
+	BitField<MouseButtonMask> last_button_state = ds->mouse_get_button_state();
+
+	MouseButtonMask mask = mouse_button_to_mask(index);
 
 	if (pressed) {
-		last_button_state |= mask;
+		last_button_state.set_flag(mask);
 	} else {
-		last_button_state &= (MouseButton)~mask;
+		last_button_state.clear_flag(mask);
 	}
 	ds->mouse_set_button_state(last_button_state);
 
@@ -407,10 +409,10 @@
 - (void)mouseDown:(NSEvent *)event {
 	if (([event modifierFlags] & NSEventModifierFlagControl)) {
 		mouse_down_control = true;
-		[self processMouseEvent:event index:MouseButton::RIGHT mask:MouseButton::MASK_RIGHT pressed:true];
+		[self processMouseEvent:event index:MouseButton::RIGHT pressed:true];
 	} else {
 		mouse_down_control = false;
-		[self processMouseEvent:event index:MouseButton::LEFT mask:MouseButton::MASK_LEFT pressed:true];
+		[self processMouseEvent:event index:MouseButton::LEFT pressed:true];
 	}
 }
 
@@ -420,9 +422,9 @@
 
 - (void)mouseUp:(NSEvent *)event {
 	if (mouse_down_control) {
-		[self processMouseEvent:event index:MouseButton::RIGHT mask:MouseButton::MASK_RIGHT pressed:false];
+		[self processMouseEvent:event index:MouseButton::RIGHT pressed:false];
 	} else {
-		[self processMouseEvent:event index:MouseButton::LEFT mask:MouseButton::MASK_LEFT pressed:false];
+		[self processMouseEvent:event index:MouseButton::LEFT pressed:false];
 	}
 }
 
@@ -469,7 +471,7 @@
 }
 
 - (void)rightMouseDown:(NSEvent *)event {
-	[self processMouseEvent:event index:MouseButton::RIGHT mask:MouseButton::MASK_RIGHT pressed:true];
+	[self processMouseEvent:event index:MouseButton::RIGHT pressed:true];
 }
 
 - (void)rightMouseDragged:(NSEvent *)event {
@@ -477,16 +479,16 @@
 }
 
 - (void)rightMouseUp:(NSEvent *)event {
-	[self processMouseEvent:event index:MouseButton::RIGHT mask:MouseButton::MASK_RIGHT pressed:false];
+	[self processMouseEvent:event index:MouseButton::RIGHT pressed:false];
 }
 
 - (void)otherMouseDown:(NSEvent *)event {
 	if ((int)[event buttonNumber] == 2) {
-		[self processMouseEvent:event index:MouseButton::MIDDLE mask:MouseButton::MASK_MIDDLE pressed:true];
+		[self processMouseEvent:event index:MouseButton::MIDDLE pressed:true];
 	} else if ((int)[event buttonNumber] == 3) {
-		[self processMouseEvent:event index:MouseButton::MB_XBUTTON1 mask:MouseButton::MASK_XBUTTON1 pressed:true];
+		[self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:true];
 	} else if ((int)[event buttonNumber] == 4) {
-		[self processMouseEvent:event index:MouseButton::MB_XBUTTON2 mask:MouseButton::MASK_XBUTTON2 pressed:true];
+		[self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:true];
 	} else {
 		return;
 	}
@@ -498,11 +500,11 @@
 
 - (void)otherMouseUp:(NSEvent *)event {
 	if ((int)[event buttonNumber] == 2) {
-		[self processMouseEvent:event index:MouseButton::MIDDLE mask:MouseButton::MASK_MIDDLE pressed:false];
+		[self processMouseEvent:event index:MouseButton::MIDDLE pressed:false];
 	} else if ((int)[event buttonNumber] == 3) {
-		[self processMouseEvent:event index:MouseButton::MB_XBUTTON1 mask:MouseButton::MASK_XBUTTON1 pressed:false];
+		[self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:false];
 	} else if ((int)[event buttonNumber] == 4) {
-		[self processMouseEvent:event index:MouseButton::MB_XBUTTON2 mask:MouseButton::MASK_XBUTTON2 pressed:false];
+		[self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:false];
 	} else {
 		return;
 	}
@@ -751,7 +753,8 @@
 	}
 
 	DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
-	MouseButton mask = mouse_button_to_mask(button);
+	MouseButtonMask mask = mouse_button_to_mask(button);
+	BitField<MouseButtonMask> last_button_state = ds->mouse_get_button_state();
 
 	Ref<InputEventMouseButton> sc;
 	sc.instantiate();
@@ -763,7 +766,7 @@
 	sc->set_pressed(true);
 	sc->set_position(wd.mouse_pos);
 	sc->set_global_position(wd.mouse_pos);
-	MouseButton last_button_state = ds->mouse_get_button_state() | (MouseButton)mask;
+	last_button_state.set_flag(mask);
 	sc->set_button_mask(last_button_state);
 	ds->mouse_set_button_state(last_button_state);
 
@@ -776,7 +779,7 @@
 	sc->set_pressed(false);
 	sc->set_position(wd.mouse_pos);
 	sc->set_global_position(wd.mouse_pos);
-	last_button_state &= (MouseButton)~mask;
+	last_button_state.clear_flag(mask);
 	sc->set_button_mask(last_button_state);
 	ds->mouse_set_button_state(last_button_state);
 

+ 15 - 12
platform/macos/joypad_macos.cpp

@@ -402,10 +402,10 @@ bool joypad::check_ff_features() {
 	return false;
 }
 
-static HatMask process_hat_value(int p_min, int p_max, int p_value, bool p_offset_hat) {
+static BitField<HatMask> process_hat_value(int p_min, int p_max, int p_value, bool p_offset_hat) {
 	int range = (p_max - p_min + 1);
 	int value = p_value - p_min;
-	HatMask hat_value = HatMask::CENTER;
+	BitField<HatMask> hat_value;
 	if (range == 4) {
 		value *= 2;
 	}
@@ -415,31 +415,34 @@ static HatMask process_hat_value(int p_min, int p_max, int p_value, bool p_offse
 
 	switch (value) {
 		case 0:
-			hat_value = HatMask::UP;
+			hat_value.set_flag(HatMask::UP);
 			break;
 		case 1:
-			hat_value = (HatMask::UP | HatMask::RIGHT);
+			hat_value.set_flag(HatMask::UP);
+			hat_value.set_flag(HatMask::RIGHT);
 			break;
 		case 2:
-			hat_value = HatMask::RIGHT;
+			hat_value.set_flag(HatMask::RIGHT);
 			break;
 		case 3:
-			hat_value = (HatMask::DOWN | HatMask::RIGHT);
+			hat_value.set_flag(HatMask::DOWN);
+			hat_value.set_flag(HatMask::RIGHT);
 			break;
 		case 4:
-			hat_value = HatMask::DOWN;
+			hat_value.set_flag(HatMask::DOWN);
 			break;
 		case 5:
-			hat_value = (HatMask::DOWN | HatMask::LEFT);
+			hat_value.set_flag(HatMask::DOWN);
+			hat_value.set_flag(HatMask::LEFT);
 			break;
 		case 6:
-			hat_value = HatMask::LEFT;
+			hat_value.set_flag(HatMask::LEFT);
 			break;
 		case 7:
-			hat_value = (HatMask::UP | HatMask::LEFT);
+			hat_value.set_flag(HatMask::UP);
+			hat_value.set_flag(HatMask::LEFT);
 			break;
 		default:
-			hat_value = HatMask::CENTER;
 			break;
 	}
 	return hat_value;
@@ -474,7 +477,7 @@ void JoypadMacOS::process_joypads() {
 		for (int j = 0; j < joy.hat_elements.size(); j++) {
 			rec_element &elem = joy.hat_elements.write[j];
 			int value = joy.get_hid_element_state(&elem);
-			HatMask hat_value = process_hat_value(elem.min, elem.max, value, joy.offset_hat);
+			BitField<HatMask> hat_value = process_hat_value(elem.min, elem.max, value, joy.offset_hat);
 			input->joy_hat(joy.id, hat_value);
 		}
 

+ 12 - 10
platform/web/display_server_web.cpp

@@ -193,12 +193,12 @@ int DisplayServerWeb::mouse_button_callback(int p_pressed, int p_button, double
 		}
 	}
 
-	MouseButton mask = Input::get_singleton()->get_mouse_button_mask();
-	MouseButton button_flag = mouse_button_to_mask(ev->get_button_index());
+	BitField<MouseButtonMask> mask = Input::get_singleton()->get_mouse_button_mask();
+	MouseButtonMask button_flag = mouse_button_to_mask(ev->get_button_index());
 	if (ev->is_pressed()) {
-		mask |= button_flag;
-	} else if ((mask & button_flag) != MouseButton::NONE) {
-		mask &= ~button_flag;
+		mask.set_flag(button_flag);
+	} else if (mask.has_flag(button_flag)) {
+		mask.clear_flag(button_flag);
 	} else {
 		// Received release event, but press was outside the canvas, so ignore.
 		return false;
@@ -218,10 +218,10 @@ int DisplayServerWeb::mouse_button_callback(int p_pressed, int p_button, double
 }
 
 void DisplayServerWeb::mouse_move_callback(double p_x, double p_y, double p_rel_x, double p_rel_y, int p_modifiers) {
-	MouseButton input_mask = Input::get_singleton()->get_mouse_button_mask();
+	BitField<MouseButtonMask> input_mask = Input::get_singleton()->get_mouse_button_mask();
 	// For motion outside the canvas, only read mouse movement if dragging
 	// started inside the canvas; imitating desktop app behavior.
-	if (!get_singleton()->cursor_inside_canvas && input_mask == MouseButton::NONE) {
+	if (!get_singleton()->cursor_inside_canvas && input_mask.is_empty()) {
 		return;
 	}
 
@@ -525,15 +525,17 @@ int DisplayServerWeb::mouse_wheel_callback(double p_delta_x, double p_delta_y) {
 	// Different browsers give wildly different delta values, and we can't
 	// interpret deltaMode, so use default value for wheel events' factor.
 
-	MouseButton button_flag = mouse_button_to_mask(ev->get_button_index());
+	MouseButtonMask button_flag = mouse_button_to_mask(ev->get_button_index());
+	BitField<MouseButtonMask> button_mask = input->get_mouse_button_mask();
+	button_mask.set_flag(button_flag);
 
 	ev->set_pressed(true);
-	ev->set_button_mask(input->get_mouse_button_mask() | button_flag);
+	ev->set_button_mask(button_mask);
 	input->parse_input_event(ev);
 
 	Ref<InputEventMouseButton> release = ev->duplicate();
 	release->set_pressed(false);
-	release->set_button_mask(MouseButton(input->get_mouse_button_mask() & ~button_flag));
+	release->set_button_mask(input->get_mouse_button_mask());
 	input->parse_input_event(release);
 
 	return true;

+ 4 - 4
platform/windows/display_server_windows.cpp

@@ -257,7 +257,7 @@ Point2i DisplayServerWindows::mouse_get_position() const {
 	return Point2i(p.x, p.y) - _get_screens_origin();
 }
 
-MouseButton DisplayServerWindows::mouse_get_button_state() const {
+BitField<MouseButtonMask> DisplayServerWindows::mouse_get_button_state() const {
 	return last_button_state;
 }
 
@@ -3162,9 +3162,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
 			mb->set_alt_pressed(alt_mem);
 			// mb->is_alt_pressed()=(wParam&MK_MENU)!=0;
 			if (mb->is_pressed()) {
-				last_button_state |= mouse_button_to_mask(mb->get_button_index());
+				last_button_state.set_flag(mouse_button_to_mask(mb->get_button_index()));
 			} else {
-				last_button_state &= ~mouse_button_to_mask(mb->get_button_index());
+				last_button_state.clear_flag(mouse_button_to_mask(mb->get_button_index()));
 			}
 			mb->set_button_mask(last_button_state);
 
@@ -3205,7 +3205,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
 				// Send release for mouse wheel.
 				Ref<InputEventMouseButton> mbd = mb->duplicate();
 				mbd->set_window_id(window_id);
-				last_button_state &= ~mouse_button_to_mask(mbd->get_button_index());
+				last_button_state.clear_flag(mouse_button_to_mask(mbd->get_button_index()));
 				mbd->set_button_mask(last_button_state);
 				mbd->set_pressed(false);
 				Input::get_singleton()->parse_input_event(mbd);

+ 2 - 2
platform/windows/display_server_windows.h

@@ -446,7 +446,7 @@ class DisplayServerWindows : public DisplayServer {
 	bool shift_mem = false;
 	bool control_mem = false;
 	bool meta_mem = false;
-	MouseButton last_button_state = MouseButton::NONE;
+	BitField<MouseButtonMask> last_button_state;
 	bool use_raw_input = false;
 	bool drop_events = false;
 	bool in_dispatch_input_event = false;
@@ -506,7 +506,7 @@ public:
 
 	virtual void warp_mouse(const Point2i &p_position) override;
 	virtual Point2i mouse_get_position() const override;
-	virtual MouseButton mouse_get_button_state() const override;
+	virtual BitField<MouseButtonMask> mouse_get_button_state() const override;
 
 	virtual void clipboard_set(const String &p_text) override;
 	virtual String clipboard_get() const override;

+ 15 - 10
platform/windows/joypad_windows.cpp

@@ -420,38 +420,43 @@ void JoypadWindows::process_joypads() {
 }
 
 void JoypadWindows::post_hat(int p_device, DWORD p_dpad) {
-	HatMask dpad_val = (HatMask)0;
+	BitField<HatMask> dpad_val;
 
 	// Should be -1 when centered, but according to docs:
 	// "Some drivers report the centered position of the POV indicator as 65,535. Determine whether the indicator is centered as follows:
 	//  BOOL POVCentered = (LOWORD(dwPOV) == 0xFFFF);"
 	// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ee416628(v%3Dvs.85)#remarks
 	if (LOWORD(p_dpad) == 0xFFFF) {
-		dpad_val = (HatMask)HatMask::CENTER;
+		// Do nothing.
+		// dpad_val.set_flag(HatMask::CENTER);
 	}
 	if (p_dpad == 0) {
-		dpad_val = (HatMask)HatMask::UP;
+		dpad_val.set_flag(HatMask::UP);
 
 	} else if (p_dpad == 4500) {
-		dpad_val = (HatMask)(HatMask::UP | HatMask::RIGHT);
+		dpad_val.set_flag(HatMask::UP);
+		dpad_val.set_flag(HatMask::RIGHT);
 
 	} else if (p_dpad == 9000) {
-		dpad_val = (HatMask)HatMask::RIGHT;
+		dpad_val.set_flag(HatMask::RIGHT);
 
 	} else if (p_dpad == 13500) {
-		dpad_val = (HatMask)(HatMask::RIGHT | HatMask::DOWN);
+		dpad_val.set_flag(HatMask::RIGHT);
+		dpad_val.set_flag(HatMask::DOWN);
 
 	} else if (p_dpad == 18000) {
-		dpad_val = (HatMask)HatMask::DOWN;
+		dpad_val.set_flag(HatMask::DOWN);
 
 	} else if (p_dpad == 22500) {
-		dpad_val = (HatMask)(HatMask::DOWN | HatMask::LEFT);
+		dpad_val.set_flag(HatMask::DOWN);
+		dpad_val.set_flag(HatMask::LEFT);
 
 	} else if (p_dpad == 27000) {
-		dpad_val = (HatMask)HatMask::LEFT;
+		dpad_val.set_flag(HatMask::LEFT);
 
 	} else if (p_dpad == 31500) {
-		dpad_val = (HatMask)(HatMask::LEFT | HatMask::UP);
+		dpad_val.set_flag(HatMask::LEFT);
+		dpad_val.set_flag(HatMask::UP);
 	}
 	input->joy_hat(p_device, dpad_val);
 }

+ 3 - 3
scene/gui/base_button.cpp

@@ -62,7 +62,7 @@ void BaseButton::gui_input(const Ref<InputEvent> &p_event) {
 	Ref<InputEventMouseButton> mouse_button = p_event;
 	bool ui_accept = p_event->is_action("ui_accept", true) && !p_event->is_echo();
 
-	bool button_masked = mouse_button.is_valid() && (mouse_button_to_mask(mouse_button->get_button_index()) & button_mask) != MouseButton::NONE;
+	bool button_masked = mouse_button.is_valid() && button_mask.has_flag(mouse_button_to_mask(mouse_button->get_button_index()));
 	if (button_masked || ui_accept) {
 		was_mouse_pressed = button_masked;
 		on_action_event(p_event);
@@ -323,11 +323,11 @@ BaseButton::ActionMode BaseButton::get_action_mode() const {
 	return action_mode;
 }
 
-void BaseButton::set_button_mask(MouseButton p_mask) {
+void BaseButton::set_button_mask(BitField<MouseButtonMask> p_mask) {
 	button_mask = p_mask;
 }
 
-MouseButton BaseButton::get_button_mask() const {
+BitField<MouseButtonMask> BaseButton::get_button_mask() const {
 	return button_mask;
 }
 

+ 3 - 3
scene/gui/base_button.h

@@ -46,7 +46,7 @@ public:
 	};
 
 private:
-	MouseButton button_mask = MouseButton::MASK_LEFT;
+	BitField<MouseButtonMask> button_mask;
 	bool toggle_mode = false;
 	bool shortcut_in_tooltip = true;
 	bool was_mouse_pressed = false;
@@ -122,8 +122,8 @@ public:
 	void set_keep_pressed_outside(bool p_on);
 	bool is_keep_pressed_outside() const;
 
-	void set_button_mask(MouseButton p_mask);
-	MouseButton get_button_mask() const;
+	void set_button_mask(BitField<MouseButtonMask> p_mask);
+	BitField<MouseButtonMask> get_button_mask() const;
 
 	void set_shortcut(const Ref<Shortcut> &p_shortcut);
 	Ref<Shortcut> get_shortcut() const;

+ 2 - 2
scene/gui/code_edit.cpp

@@ -380,13 +380,13 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
 		}
 
 		if (symbol_lookup_on_click_enabled) {
-			if (mm->is_command_or_control_pressed() && mm->get_button_mask() == MouseButton::NONE) {
+			if (mm->is_command_or_control_pressed() && mm->get_button_mask().is_empty()) {
 				symbol_lookup_pos = get_line_column_at_pos(mpos);
 				symbol_lookup_new_word = get_word_at_pos(mpos);
 				if (symbol_lookup_new_word != symbol_lookup_word) {
 					emit_signal(SNAME("symbol_validate"), symbol_lookup_new_word);
 				}
-			} else if (!mm->is_command_or_control_pressed() || (mm->get_button_mask() != MouseButton::NONE && symbol_lookup_pos != get_line_column_at_pos(mpos))) {
+			} else if (!mm->is_command_or_control_pressed() || (!mm->get_button_mask().is_empty() && symbol_lookup_pos != get_line_column_at_pos(mpos))) {
 				set_symbol_lookup_word_as_valid(false);
 			}
 		}

+ 1 - 1
scene/gui/line_edit.cpp

@@ -394,7 +394,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
 			}
 		}
 
-		if ((m->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+		if (m->get_button_mask().has_flag(MouseButtonMask::LEFT)) {
 			if (selection.creating) {
 				set_caret_at_pixel_pos(m->get_position().x);
 				selection_fill_at_caret();

+ 2 - 2
scene/gui/popup_menu.cpp

@@ -395,10 +395,10 @@ void PopupMenu::gui_input(const Ref<InputEvent> &p_event) {
 			// Activate the item on release of either the left mouse button or
 			// any mouse button held down when the popup was opened.
 			// This allows for opening the popup and triggering an action in a single mouse click.
-			if (button_idx == MouseButton::LEFT || (initial_button_mask & mouse_button_to_mask(button_idx)) != MouseButton::NONE) {
+			if (button_idx == MouseButton::LEFT || initial_button_mask.has_flag(mouse_button_to_mask(button_idx))) {
 				bool was_during_grabbed_click = during_grabbed_click;
 				during_grabbed_click = false;
-				initial_button_mask = MouseButton::NONE;
+				initial_button_mask.clear();
 
 				// Disable clicks under a time threshold to avoid selection right when opening the popup.
 				uint64_t now = OS::get_singleton()->get_ticks_msec();

+ 1 - 1
scene/gui/popup_menu.h

@@ -92,7 +92,7 @@ class PopupMenu : public Popup {
 	Timer *submenu_timer = nullptr;
 	List<Rect2> autohide_areas;
 	Vector<Item> items;
-	MouseButton initial_button_mask = MouseButton::NONE;
+	BitField<MouseButtonMask> initial_button_mask;
 	bool during_grabbed_click = false;
 	int mouse_over = -1;
 	int submenu_over = -1;

+ 1 - 1
scene/gui/spin_box.cpp

@@ -176,7 +176,7 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) {
 
 	Ref<InputEventMouseMotion> mm = p_event;
 
-	if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+	if (mm.is_valid() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 		if (drag.enabled) {
 			drag.diff_y += mm->get_relative().y;
 			double diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8) * SIGN(drag.diff_y);

+ 1 - 1
scene/gui/text_edit.cpp

@@ -1906,7 +1906,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
 			mpos.x = get_size().x - mpos.x;
 		}
 
-		if ((mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE && get_viewport()->gui_get_drag_data() == Variant()) { // Ignore if dragging.
+		if (mm->get_button_mask().has_flag(MouseButtonMask::LEFT) && get_viewport()->gui_get_drag_data() == Variant()) { // Ignore if dragging.
 			_reset_caret_blink_timer();
 
 			if (draw_minimap && !dragging_selection) {

+ 1 - 1
scene/gui/view_panner.cpp

@@ -114,7 +114,7 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
 	if (k.is_valid()) {
 		if (pan_view_shortcut.is_valid() && pan_view_shortcut->matches_event(k)) {
 			pan_key_pressed = k->is_pressed();
-			if (simple_panning_enabled || (Input::get_singleton()->get_mouse_button_mask() & MouseButton::LEFT) != MouseButton::NONE) {
+			if (simple_panning_enabled || Input::get_singleton()->get_mouse_button_mask().has_flag(MouseButtonMask::LEFT)) {
 				is_dragging = pan_key_pressed;
 			}
 			return true;

+ 19 - 18
scene/main/viewport.cpp

@@ -603,9 +603,9 @@ void Viewport::_process_picking() {
 			physics_last_mouse_state.meta = mb->is_meta_pressed();
 
 			if (mb->is_pressed()) {
-				physics_last_mouse_state.mouse_mask |= mouse_button_to_mask(mb->get_button_index());
+				physics_last_mouse_state.mouse_mask.set_flag(mouse_button_to_mask(mb->get_button_index()));
 			} else {
-				physics_last_mouse_state.mouse_mask &= ~mouse_button_to_mask(mb->get_button_index());
+				physics_last_mouse_state.mouse_mask.clear_flag(mouse_button_to_mask(mb->get_button_index()));
 
 				// If touch mouse raised, assume we don't know last mouse pos until new events come
 				if (mb->get_device() == InputEvent::DEVICE_ID_TOUCH_MOUSE) {
@@ -1496,19 +1496,20 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
 		Point2 mpos = mb->get_position();
 		if (mb->is_pressed()) {
 			Size2 pos = mpos;
-			if (gui.mouse_focus_mask != MouseButton::NONE) {
+			if (!gui.mouse_focus_mask.is_empty()) {
 				// Do not steal mouse focus and stuff while a focus mask exists.
-				gui.mouse_focus_mask |= mouse_button_to_mask(mb->get_button_index());
+				gui.mouse_focus_mask.set_flag(mouse_button_to_mask(mb->get_button_index()));
 			} else {
 				gui.mouse_focus = gui_find_control(pos);
 				gui.last_mouse_focus = gui.mouse_focus;
 
 				if (!gui.mouse_focus) {
-					gui.mouse_focus_mask = MouseButton::NONE;
+					gui.mouse_focus_mask.clear();
 					return;
 				}
 
-				gui.mouse_focus_mask = mouse_button_to_mask(mb->get_button_index());
+				gui.mouse_focus_mask.clear();
+				gui.mouse_focus_mask.set_flag(mouse_button_to_mask(mb->get_button_index()));
 
 				if (mb->get_button_index() == MouseButton::LEFT) {
 					gui.drag_accum = Vector2();
@@ -1578,7 +1579,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
 				_perform_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos);
 			}
 
-			gui.mouse_focus_mask &= ~mouse_button_to_mask(mb->get_button_index()); // Remove from mask.
+			gui.mouse_focus_mask.clear_flag(mouse_button_to_mask(mb->get_button_index())); // Remove from mask.
 
 			if (!gui.mouse_focus) {
 				// Release event is only sent if a mouse focus (previously pressed button) exists.
@@ -1597,7 +1598,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
 			// Disable mouse focus if needed before calling input,
 			// this makes popups on mouse press event work better,
 			// as the release will never be received otherwise.
-			if (gui.mouse_focus_mask == MouseButton::NONE) {
+			if (gui.mouse_focus_mask.is_empty()) {
 				gui.mouse_focus = nullptr;
 				gui.forced_mouse_focus = false;
 			}
@@ -1619,7 +1620,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
 		Point2 mpos = mm->get_position();
 
 		// Drag & drop.
-		if (!gui.drag_attempted && gui.mouse_focus && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
+		if (!gui.drag_attempted && gui.mouse_focus && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
 			gui.drag_accum += mm->get_relative();
 			float len = gui.drag_accum.length();
 			if (len > 10) {
@@ -1633,7 +1634,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
 							if (gui.drag_data.get_type() != Variant::NIL) {
 								gui.mouse_focus = nullptr;
 								gui.forced_mouse_focus = false;
-								gui.mouse_focus_mask = MouseButton::NONE;
+								gui.mouse_focus_mask.clear();
 								break;
 							} else {
 								Control *drag_preview = _gui_get_drag_preview();
@@ -1701,7 +1702,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
 			mm->set_velocity(velocity);
 			mm->set_relative(rel);
 
-			if (mm->get_button_mask() == MouseButton::NONE) {
+			if (mm->get_button_mask().is_empty()) {
 				// Nothing pressed.
 
 				bool is_tooltip_shown = false;
@@ -1744,7 +1745,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
 				Control *c = over;
 				Vector2 cpos = pos;
 				while (c) {
-					if (gui.mouse_focus_mask != MouseButton::NONE || c->has_point(cpos)) {
+					if (!gui.mouse_focus_mask.is_empty() || c->has_point(cpos)) {
 						cursor_shape = c->get_cursor_shape(cpos);
 					} else {
 						cursor_shape = Control::CURSOR_ARROW;
@@ -2103,7 +2104,7 @@ void Viewport::_gui_cleanup_internal_state(Ref<InputEvent> p_event) {
 	Ref<InputEventMouseButton> mb = p_event;
 	if (mb.is_valid()) {
 		if (!mb->is_pressed()) {
-			gui.mouse_focus_mask &= ~mouse_button_to_mask(mb->get_button_index()); // Remove from mask.
+			gui.mouse_focus_mask.clear_flag(mouse_button_to_mask(mb->get_button_index())); // Remove from mask.
 		}
 	}
 }
@@ -2194,7 +2195,7 @@ void Viewport::_gui_remove_control(Control *p_control) {
 	if (gui.mouse_focus == p_control) {
 		gui.mouse_focus = nullptr;
 		gui.forced_mouse_focus = false;
-		gui.mouse_focus_mask = MouseButton::NONE;
+		gui.mouse_focus_mask.clear();
 	}
 	if (gui.last_mouse_focus == p_control) {
 		gui.last_mouse_focus = nullptr;
@@ -2263,10 +2264,10 @@ void Viewport::_drop_mouse_over() {
 
 void Viewport::_drop_mouse_focus() {
 	Control *c = gui.mouse_focus;
-	MouseButton mask = gui.mouse_focus_mask;
+	BitField<MouseButtonMask> mask = gui.mouse_focus_mask;
 	gui.mouse_focus = nullptr;
 	gui.forced_mouse_focus = false;
-	gui.mouse_focus_mask = MouseButton::NONE;
+	gui.mouse_focus_mask.clear();
 
 	for (int i = 0; i < 3; i++) {
 		if ((int)mask & (1 << i)) {
@@ -2374,7 +2375,7 @@ void Viewport::_post_gui_grab_click_focus() {
 			return;
 		}
 
-		MouseButton mask = gui.mouse_focus_mask;
+		BitField<MouseButtonMask> mask = gui.mouse_focus_mask;
 		Point2 click = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos);
 
 		for (int i = 0; i < 3; i++) {
@@ -3239,7 +3240,7 @@ void Viewport::pass_mouse_focus_to(Viewport *p_viewport, Control *p_control) {
 
 		gui.mouse_focus = nullptr;
 		gui.forced_mouse_focus = false;
-		gui.mouse_focus_mask = MouseButton::NONE;
+		gui.mouse_focus_mask.clear();
 	}
 }
 

+ 2 - 2
scene/main/viewport.h

@@ -259,7 +259,7 @@ private:
 		bool control = false;
 		bool shift = false;
 		bool meta = false;
-		MouseButton mouse_mask = MouseButton::NONE;
+		BitField<MouseButtonMask> mouse_mask;
 
 	} physics_last_mouse_state;
 
@@ -358,7 +358,7 @@ private:
 		Control *mouse_focus = nullptr;
 		Control *last_mouse_focus = nullptr;
 		Control *mouse_click_grabber = nullptr;
-		MouseButton mouse_focus_mask = MouseButton::NONE;
+		BitField<MouseButtonMask> mouse_focus_mask;
 		Control *key_focus = nullptr;
 		Control *mouse_over = nullptr;
 		Control *drag_mouse_over = nullptr;

+ 2 - 2
servers/display_server.cpp

@@ -331,8 +331,8 @@ Point2i DisplayServer::mouse_get_position() const {
 	ERR_FAIL_V_MSG(Point2i(), "Mouse is not supported by this display server.");
 }
 
-MouseButton DisplayServer::mouse_get_button_state() const {
-	ERR_FAIL_V_MSG(MouseButton::NONE, "Mouse is not supported by this display server.");
+BitField<MouseButtonMask> DisplayServer::mouse_get_button_state() const {
+	ERR_FAIL_V_MSG(0, "Mouse is not supported by this display server.");
 }
 
 void DisplayServer::clipboard_set(const String &p_text) {

+ 1 - 1
servers/display_server.h

@@ -230,7 +230,7 @@ public:
 
 	virtual void warp_mouse(const Point2i &p_position);
 	virtual Point2i mouse_get_position() const;
-	virtual MouseButton mouse_get_button_state() const;
+	virtual BitField<MouseButtonMask> mouse_get_button_state() const;
 
 	virtual void clipboard_set(const String &p_text);
 	virtual String clipboard_get() const;

+ 4 - 4
tests/scene/test_code_edit.h

@@ -3111,15 +3111,15 @@ TEST_CASE("[SceneTree][CodeEdit] completion") {
 
 			Point2 caret_pos = code_edit->get_caret_draw_pos();
 			caret_pos.y += code_edit->get_line_height();
-			SEND_GUI_MOUSE_BUTTON_EVENT(code_edit, caret_pos, MouseButton::WHEEL_DOWN, MouseButton::NONE, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(code_edit, caret_pos, MouseButton::WHEEL_DOWN, 0, Key::NONE);
 			CHECK(code_edit->get_code_completion_selected_index() == 1);
 
-			SEND_GUI_MOUSE_BUTTON_EVENT(code_edit, caret_pos, MouseButton::WHEEL_UP, MouseButton::NONE, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(code_edit, caret_pos, MouseButton::WHEEL_UP, 0, Key::NONE);
 			CHECK(code_edit->get_code_completion_selected_index() == 0);
 
 			/* Single click selects. */
 			caret_pos.y += code_edit->get_line_height() * 2;
-			SEND_GUI_MOUSE_BUTTON_EVENT(code_edit, caret_pos, MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(code_edit, caret_pos, MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
 			CHECK(code_edit->get_code_completion_selected_index() == 2);
 
 			/* Double click inserts. */
@@ -3330,7 +3330,7 @@ TEST_CASE("[SceneTree][CodeEdit] symbol lookup") {
 
 		Point2 caret_pos = code_edit->get_caret_draw_pos();
 		caret_pos.x += 60;
-		SEND_GUI_MOUSE_BUTTON_EVENT(code_edit, caret_pos, MouseButton::NONE, MouseButton::NONE, Key::NONE);
+		SEND_GUI_MOUSE_BUTTON_EVENT(code_edit, caret_pos, MouseButton::NONE, 0, Key::NONE);
 		CHECK(code_edit->get_text_for_symbol_lookup() == "this is s" + String::chr(0xFFFF) + "ome text");
 
 		SIGNAL_WATCH(code_edit, "symbol_validate");

+ 29 - 29
tests/scene/test_text_edit.h

@@ -891,8 +891,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
 			text_edit->grab_focus();
 			MessageQueue::get_singleton()->flush();
 
-			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 1), MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
-			SEND_GUI_MOUSE_MOTION_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 7), MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 1), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
+			SEND_GUI_MOUSE_MOTION_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 7), MouseButtonMask::LEFT, Key::NONE);
 			CHECK(text_edit->has_selection());
 			CHECK(text_edit->get_selected_text() == "for s");
 			CHECK(text_edit->get_selection_mode() == TextEdit::SELECTION_MODE_POINTER);
@@ -903,12 +903,12 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
 			CHECK(text_edit->get_caret_line() == 1);
 			CHECK(text_edit->get_caret_column() == 5);
 
-			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 9), MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 9), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
 			CHECK_FALSE(text_edit->has_selection());
 
 			text_edit->set_selecting_enabled(false);
-			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 1), MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
-			SEND_GUI_MOUSE_MOTION_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 7), MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 1), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
+			SEND_GUI_MOUSE_MOTION_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 7), MouseButtonMask::LEFT, Key::NONE);
 			CHECK_FALSE(text_edit->has_selection());
 			CHECK(text_edit->get_caret_line() == 1);
 			CHECK(text_edit->get_caret_column() == 5);
@@ -935,7 +935,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
 			CHECK(text_edit->get_caret_column() == 3);
 			SIGNAL_CHECK("caret_changed", empty_signal_args);
 
-			SEND_GUI_MOUSE_MOTION_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 7), MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_MOTION_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 7), MouseButtonMask::LEFT, Key::NONE);
 			CHECK(text_edit->has_selection());
 			CHECK(text_edit->get_selected_text() == "for selection");
 			CHECK(text_edit->get_selection_mode() == TextEdit::SELECTION_MODE_WORD);
@@ -949,7 +949,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
 
 			Point2i line_0 = text_edit->get_pos_at_line_column(0, 0);
 			line_0.y /= 2;
-			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, line_0, MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, line_0, MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
 			CHECK_FALSE(text_edit->has_selection());
 
 			text_edit->set_selecting_enabled(false);
@@ -968,7 +968,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
 			MessageQueue::get_singleton()->flush();
 
 			SEND_GUI_DOUBLE_CLICK(text_edit, text_edit->get_pos_at_line_column(0, 2), Key::NONE);
-			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 2), MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 2), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
 			CHECK(text_edit->has_selection());
 			CHECK(text_edit->get_selected_text() == "for selection");
 			CHECK(text_edit->get_selection_mode() == TextEdit::SELECTION_MODE_LINE);
@@ -981,12 +981,12 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
 
 			Point2i line_0 = text_edit->get_pos_at_line_column(0, 0);
 			line_0.y /= 2;
-			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, line_0, MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, line_0, MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
 			CHECK_FALSE(text_edit->has_selection());
 
 			text_edit->set_selecting_enabled(false);
 			SEND_GUI_DOUBLE_CLICK(text_edit, text_edit->get_pos_at_line_column(0, 2), Key::NONE);
-			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 2), MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 2), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
 			CHECK_FALSE(text_edit->has_selection());
 			CHECK(text_edit->get_caret_line() == 1);
 			CHECK(text_edit->get_caret_column() == 0);
@@ -1000,8 +1000,8 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
 			text_edit->set_text("this is some text\nfor selection");
 			MessageQueue::get_singleton()->flush();
 
-			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 0), MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
-			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 7), MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE | KeyModifierMask::SHIFT);
+			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 0), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 7), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE | KeyModifierMask::SHIFT);
 			CHECK(text_edit->has_selection());
 			CHECK(text_edit->get_selected_text() == "for s");
 			CHECK(text_edit->get_selection_mode() == TextEdit::SELECTION_MODE_POINTER);
@@ -1012,12 +1012,12 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
 			CHECK(text_edit->get_caret_line() == 1);
 			CHECK(text_edit->get_caret_column() == 5);
 
-			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 9), MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 9), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
 			CHECK_FALSE(text_edit->has_selection());
 
 			text_edit->set_selecting_enabled(false);
-			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 0), MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
-			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 7), MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE | KeyModifierMask::SHIFT);
+			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 0), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 7), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE | KeyModifierMask::SHIFT);
 			CHECK_FALSE(text_edit->has_selection());
 			CHECK(text_edit->get_caret_line() == 1);
 			CHECK(text_edit->get_caret_column() == 5);
@@ -1149,19 +1149,19 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
 
 			Point2i line_0 = text_edit->get_pos_at_line_column(0, 0);
 			line_0.y /= 2;
-			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, line_0, MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, line_0, MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
 			CHECK(text_edit->is_mouse_over_selection());
-			SEND_GUI_MOUSE_MOTION_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 7), MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_MOTION_EVENT(text_edit, text_edit->get_pos_at_line_column(0, 7), MouseButtonMask::LEFT, Key::NONE);
 			CHECK(text_edit->get_viewport()->gui_is_dragging());
 			CHECK(text_edit->get_viewport()->gui_get_drag_data() == "drag me");
 
 			line_0 = target_text_edit->get_pos_at_line_column(0, 0);
 			line_0.y /= 2;
 			line_0.x += 401; // As empty add one.
-			SEND_GUI_MOUSE_MOTION_EVENT(target_text_edit, line_0, MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_MOTION_EVENT(target_text_edit, line_0, MouseButtonMask::LEFT, Key::NONE);
 			CHECK(text_edit->get_viewport()->gui_is_dragging());
 
-			SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(target_text_edit, line_0, MouseButton::LEFT, MouseButton::MASK_LEFT, Key::NONE);
+			SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(target_text_edit, line_0, MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
 
 			CHECK_FALSE(text_edit->get_viewport()->gui_is_dragging());
 			CHECK(text_edit->get_text() == "");
@@ -3093,14 +3093,14 @@ TEST_CASE("[SceneTree][TextEdit] context menu") {
 	CHECK_FALSE(text_edit->is_context_menu_enabled());
 
 	CHECK_FALSE(text_edit->is_menu_visible());
-	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(600, 10), MouseButton::RIGHT, MouseButton::MASK_RIGHT, Key::NONE);
+	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(600, 10), MouseButton::RIGHT, MouseButtonMask::RIGHT, Key::NONE);
 	CHECK_FALSE(text_edit->is_menu_visible());
 
 	text_edit->set_context_menu_enabled(true);
 	CHECK(text_edit->is_context_menu_enabled());
 
 	CHECK_FALSE(text_edit->is_menu_visible());
-	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(700, 10), MouseButton::RIGHT, MouseButton::MASK_RIGHT, Key::NONE);
+	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(700, 10), MouseButton::RIGHT, MouseButtonMask::RIGHT, Key::NONE);
 	CHECK(text_edit->is_menu_visible());
 
 	memdelete(text_edit);
@@ -3340,13 +3340,13 @@ TEST_CASE("[SceneTree][TextEdit] caret") {
 	text_edit->set_move_caret_on_right_click_enabled(false);
 	CHECK_FALSE(text_edit->is_move_caret_on_right_click_enabled());
 
-	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(100, 1), MouseButton::RIGHT, MouseButton::MASK_RIGHT, Key::NONE);
+	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(100, 1), MouseButton::RIGHT, MouseButtonMask::RIGHT, Key::NONE);
 	CHECK(text_edit->get_caret_column() == caret_col);
 
 	text_edit->set_move_caret_on_right_click_enabled(true);
 	CHECK(text_edit->is_move_caret_on_right_click_enabled());
 
-	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(100, 1), MouseButton::RIGHT, MouseButton::MASK_RIGHT, Key::NONE);
+	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(100, 1), MouseButton::RIGHT, MouseButtonMask::RIGHT, Key::NONE);
 	CHECK(text_edit->get_caret_column() != caret_col);
 
 	text_edit->set_move_caret_on_right_click_enabled(false);
@@ -3860,28 +3860,28 @@ TEST_CASE("[SceneTree][TextEdit] viewport") {
 
 	// Scroll.
 	int v_scroll = text_edit->get_v_scroll();
-	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_DOWN, MouseButton::WHEEL_DOWN, Key::NONE);
+	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_DOWN, 0, Key::NONE);
 	CHECK(text_edit->get_v_scroll() > v_scroll);
-	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_UP, MouseButton::WHEEL_UP, Key::NONE);
+	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_UP, 0, Key::NONE);
 	CHECK(text_edit->get_v_scroll() == v_scroll);
 
 	// smooth scroll speed.
 	text_edit->set_smooth_scroll_enabled(true);
 
 	v_scroll = text_edit->get_v_scroll();
-	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_DOWN, MouseButton::WHEEL_DOWN, Key::NONE);
+	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_DOWN, 0, Key::NONE);
 	text_edit->notification(TextEdit::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
 	CHECK(text_edit->get_v_scroll() >= v_scroll);
-	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_UP, MouseButton::WHEEL_UP, Key::NONE);
+	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_UP, 0, Key::NONE);
 	text_edit->notification(TextEdit::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
 	CHECK(text_edit->get_v_scroll() == v_scroll);
 
 	v_scroll = text_edit->get_v_scroll();
 	text_edit->set_v_scroll_speed(10000);
-	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_DOWN, MouseButton::WHEEL_DOWN, Key::NONE);
+	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_DOWN, 0, Key::NONE);
 	text_edit->notification(TextEdit::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
 	CHECK(text_edit->get_v_scroll() >= v_scroll);
-	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_UP, MouseButton::WHEEL_UP, Key::NONE);
+	SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_UP, 0, Key::NONE);
 	text_edit->notification(TextEdit::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
 	CHECK(text_edit->get_v_scroll() == v_scroll);
 

+ 7 - 7
tests/test_macros.h

@@ -136,7 +136,7 @@ int register_test_command(String p_command, TestFunc p_function);
 // SEND_GUI_KEY_EVENT - takes an object and a keycode set.   e.g SEND_GUI_KEY_EVENT(code_edit, Key::A | KeyModifierMask::META).
 // SEND_GUI_MOUSE_BUTTON_EVENT - takes an object, position, mouse button, mouse mask and modifiers e.g SEND_GUI_MOUSE_BUTTON_EVENT(code_edit, Vector2(50, 50), MOUSE_BUTTON_NONE, MOUSE_BUTTON_NONE, Key::None);
 // SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT - takes an object, position, mouse button, mouse mask and modifiers e.g SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(code_edit, Vector2(50, 50), MOUSE_BUTTON_NONE, MOUSE_BUTTON_NONE, Key::None);
-// SEND_GUI_MOUSE_MOTION_EVENT - takes an object, position, mouse mask and modifiers e.g SEND_GUI_MOUSE_MOTION_EVENT(code_edit, Vector2(50, 50), MouseButton::MASK_LEFT, KeyModifierMask::META);
+// SEND_GUI_MOUSE_MOTION_EVENT - takes an object, position, mouse mask and modifiers e.g SEND_GUI_MOUSE_MOTION_EVENT(code_edit, Vector2(50, 50), MouseButtonMask::LEFT, KeyModifierMask::META);
 // SEND_GUI_DOUBLE_CLICK - takes an object, position and modifiers. e.g SEND_GUI_DOUBLE_CLICK(code_edit, Vector2(50, 50), KeyModifierMask::META);
 
 #define SEND_GUI_ACTION(m_object, m_action)                                                           \
@@ -188,12 +188,12 @@ int register_test_command(String p_command, TestFunc p_function);
 		MessageQueue::get_singleton()->flush();                                                  \
 	}
 
-#define SEND_GUI_DOUBLE_CLICK(m_object, m_local_pos, m_modifers)                                          \
-	{                                                                                                     \
-		_CREATE_GUI_MOUSE_EVENT(m_object, m_local_pos, MouseButton::LEFT, MouseButton::LEFT, m_modifers); \
-		event->set_double_click(true);                                                                    \
-		m_object->get_viewport()->push_input(event);                                                      \
-		MessageQueue::get_singleton()->flush();                                                           \
+#define SEND_GUI_DOUBLE_CLICK(m_object, m_local_pos, m_modifers)                          \
+	{                                                                                     \
+		_CREATE_GUI_MOUSE_EVENT(m_object, m_local_pos, MouseButton::LEFT, 0, m_modifers); \
+		event->set_double_click(true);                                                    \
+		m_object->get_viewport()->push_input(event);                                      \
+		MessageQueue::get_singleton()->flush();                                           \
 	}
 
 // We toggle _print_error_enabled to prevent display server not supported warnings.