Use BitField<> in core type masks

* All core types masks are now correctly marked as bitfields.
* The enum hacks in MouseButtonMask and many other types are gone. This ensures that binders to other languages non C++ can actually implement type safe bitmasks.
* Most bitmask operations replaced by functions in BitField<>
* Key is still a problem because its enum and mask at the same time. While it kind of works in C++, this most likely can't be implemented safely in other languages and will have to be changed at some point. Mostly left as-is.
* Documentation and API dump updated to reflect bitfields in core types.
This commit is contained in:
Juan Linietsky
2023-01-08 00:55:54 +01:00
parent fcba87e696
commit 2b815df3c1
69 changed files with 490 additions and 442 deletions

View File

@@ -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];

View File

@@ -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);

View File

@@ -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));
}
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 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);
}
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

View File

@@ -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.

View File

@@ -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;